diff --git a/go.mod b/go.mod index 1225a3b91..05858c892 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/Netflix/go-expect v0.0.0-20210722184520-ef0bf57d82b3 github.com/alecthomas/jsonschema v0.0.0-20210526225647-edb03dcab7bc github.com/buildpacks/pack v0.24.0 - github.com/cloudevents/sdk-go/v2 v2.5.0 + github.com/cloudevents/sdk-go/v2 v2.8.0 github.com/containers/image/v5 v5.19.1 github.com/coreos/go-semver v0.3.0 github.com/docker/cli v20.10.12+incompatible @@ -18,7 +18,7 @@ require ( github.com/go-git/go-billy/v5 v5.3.1 github.com/go-git/go-git/v5 v5.4.2 github.com/google/go-cmp v0.5.7 - github.com/google/go-containerregistry v0.8.1-0.20220219142810-1571d7fdc46e + github.com/google/go-containerregistry v0.8.1-0.20220414143355-892d7a808387 github.com/google/uuid v1.3.0 github.com/hinshun/vt10x v0.0.0-20180809195222-d55458df857c github.com/mitchellh/go-homedir v1.1.0 @@ -34,21 +34,23 @@ require ( golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce gopkg.in/yaml.v2 v2.4.0 - k8s.io/api v0.23.4 - k8s.io/apimachinery v0.23.4 + k8s.io/api v0.23.5 + k8s.io/apimachinery v0.23.5 k8s.io/client-go v1.5.2 k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 - knative.dev/client v0.28.0 - knative.dev/eventing v0.28.4 + knative.dev/client v0.29.0 + knative.dev/eventing v0.29.2-0.20220420140829-ce4fe0990d23 knative.dev/hack v0.0.0-20220128200847-51a42b2eb63e - knative.dev/pkg v0.0.0-20220222214539-0b8a9403de7e - knative.dev/serving v0.28.4 + knative.dev/networking v0.0.0-20220120045035-ec849677a316 // indirect + knative.dev/pkg v0.0.0-20220222214439-083dd97300e1 + knative.dev/serving v0.29.5 ) replace ( + // Tekton Triggers imports old google/cel-go, should be fixed with tektoncd/cli >=v0.24.x transitively + github.com/google/cel-go => github.com/google/cel-go v0.11.2 // update docker to be compatible with version used by pack and removes invalid pseudo-version github.com/openshift/source-to-image => github.com/boson-project/source-to-image v1.3.2 - // Pin k8s.io dependencies to align with Knative and Tekton needs k8s.io/api => k8s.io/api v0.22.5 k8s.io/apimachinery => k8s.io/apimachinery v0.22.5 diff --git a/go.sum b/go.sum index 922f12735..e81a6804d 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,7 @@ 4d63.com/gochecknoglobals v0.1.0/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo= bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= bitbucket.org/creachadair/shell v0.0.6/go.mod h1:8Qqi/cYk7vPnsOePHroKXDJYmb5x7ENhtiFtfZq8K+M= bou.ke/monkey v1.0.2/go.mod h1:OqickVX3tNx6t33n1xvtTtu85YN5s6cKwVug+oHMaIA= cloud.google.com/go v0.25.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= @@ -56,8 +57,9 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= cloud.google.com/go/compute v1.1.0/go.mod h1:2NIffxgWfORSI7EOYMFatGTfjMLnqrOKBEyYb6NoRgA= -cloud.google.com/go/compute v1.3.0 h1:mPL/MzDDYHsh5tHRS9mhmhWlcgClCrCa6ApQCU6wnHI= cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0 h1:b1zWmYuuHz7gO9kDcM/EpHGr06UgsYNRpNJzI2kFiLM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= @@ -117,6 +119,7 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7 git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= git.apache.org/thrift.git v0.12.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774/go.mod h1:6/0dYRLLXyJjbkIPeeGyoJ/eKOSI0eU6eTlCBYibgd0= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg= github.com/AdaLogics/go-fuzz-headers v0.0.0-20211102141018-f7be0cbad29c/go.mod h1:WpB7kf89yJUETZxQnP1kgYPNwlT2jjdDYUCoxVggM3g= github.com/AkihiroSuda/containerd-fuse-overlayfs v1.0.0/go.mod h1:0mMDvQFeLbbn1Wy8P2j3hwFhqBq+FKn8OZPno8WLmp8= github.com/AlecAivazis/survey/v2 v2.2.12/go.mod h1:6d4saEvBsfSHXeN1a5OA5m2+HJ2LuVokllnC77pAIKI= @@ -150,6 +153,7 @@ github.com/Azure/azure-sdk-for-go v61.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9mo github.com/Azure/azure-sdk-for-go v61.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v61.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v61.5.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v62.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-service-bus-go v0.9.1/go.mod h1:yzBx6/BUGfjfeqbRZny9AQIbIe3AcV9WZbAdpkoXOa0= github.com/Azure/azure-service-bus-go v0.11.5/go.mod h1:MI6ge2CuQWBVq+ly456MY7XqNLJip5LO1iSFodbNLbU= github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0= @@ -265,8 +269,9 @@ github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JP github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= @@ -275,6 +280,7 @@ github.com/Microsoft/hcsshim v0.8.10/go.mod h1:g5uw8EV2mAlzqe94tfNBNdr89fnbD/n3H github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= +github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= github.com/Microsoft/hcsshim v0.9.2 h1:wB06W5aYFfUB3IvootYAY2WnOmIdgPGfqSI6tufQNnY= @@ -340,6 +346,7 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= +github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= @@ -349,8 +356,9 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/antlr/antlr4 v0.0.0-20200503195918-621b933c7a7f h1:0cEys61Sr2hUBEXfNV8eyQP01oZuBgoMeHunebPirK8= -github.com/antlr/antlr4 v0.0.0-20200503195918-621b933c7a7f/go.mod h1:T7PbCXFs94rrTttyxjbyT5+/1V8T2TYDejxUfHJjw1Y= +github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20211221011931-643d94fcab96/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= +github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220209173558-ad29539cd2e9 h1:zvkJv+9Pxm1nnEMcKnShREt4qtduHKz4iw4AB4ul0Ao= +github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220209173558-ad29539cd2e9/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= github.com/apache/beam v2.28.0+incompatible/go.mod h1:/8NX3Qi8vGstDLLaeaU7+lzVEu/ACaQhYjeefzQ0y1o= github.com/apache/beam v2.32.0+incompatible/go.mod h1:/8NX3Qi8vGstDLLaeaU7+lzVEu/ACaQhYjeefzQ0y1o= @@ -412,43 +420,53 @@ github.com/aws/aws-sdk-go-v2 v1.7.1/go.mod h1:L5LuPC1ZgDr2xQS7AmIec/Jlc7O/Y1u2Kx github.com/aws/aws-sdk-go-v2 v1.11.0/go.mod h1:SQfA+m2ltnu1cA0soUkj4dRSsmITiVQUJvBIZjzfPyQ= github.com/aws/aws-sdk-go-v2 v1.12.0/go.mod h1:tWhQI5N5SiMawto3uMAQJU5OUN/1ivhDDHq7HTsJvZ0= github.com/aws/aws-sdk-go-v2 v1.13.0/go.mod h1:L6+ZpqHaLbAaxsqV0L4cvxZY7QupWJB4fhkf8LXvC7w= +github.com/aws/aws-sdk-go-v2 v1.14.0/go.mod h1:ZA3Y8V0LrlWj63MQAnRHgKf/5QB//LSZCPNWlWrNGLU= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.0.0/go.mod h1:Xn6sxgRuIDflLRJFj5Ev7UxABIkNbccFPV/p8itDReM= github.com/aws/aws-sdk-go-v2/config v1.5.0/go.mod h1:RWlPOAW3E3tbtNAqTwvSW54Of/yP3oiZXMI0xfUdjyA= github.com/aws/aws-sdk-go-v2/config v1.10.1/go.mod h1:auIv5pIIn3jIBHNRcVQcsczn6Pfa6Dyv80Fai0ueoJU= github.com/aws/aws-sdk-go-v2/config v1.12.0/go.mod h1:GQONFVSDdG6RRho1C730SGNyDhS1kSTnxpOE76ptBqo= github.com/aws/aws-sdk-go-v2/config v1.13.0/go.mod h1:Pjv2OafecIn+4miw9VFDCr06YhKyf/oKOkIcpQOgWKk= github.com/aws/aws-sdk-go-v2/config v1.13.1/go.mod h1:Ba5Z4yL/UGbjQUzsiaN378YobhFo0MLfueXGiOsYtEs= +github.com/aws/aws-sdk-go-v2/config v1.14.0/go.mod h1:GKDRrvsq/PTaOYc9252u8Uah1hsIdtor4oIrFvUNPNM= github.com/aws/aws-sdk-go-v2/credentials v1.3.1/go.mod h1:r0n73xwsIVagq8RsxmZbGSRQFj9As3je72C2WzUIToc= github.com/aws/aws-sdk-go-v2/credentials v1.6.1/go.mod h1:QyvQk1IYTqBWSi1T6UgT/W8DMxBVa5pVuLFSRLLhGf8= github.com/aws/aws-sdk-go-v2/credentials v1.7.0/go.mod h1:Kmq64kahHJtXfmnEwnvRKeNjLBqkdP++Itln9BmQerE= github.com/aws/aws-sdk-go-v2/credentials v1.8.0/go.mod h1:gnMo58Vwx3Mu7hj1wpcG8DI0s57c9o42UQ6wgTQT5to= +github.com/aws/aws-sdk-go-v2/credentials v1.9.0/go.mod h1:PyHKqk/+tJuDY7T8R580S1j/AcSD+ODeUZ99CAUKLqQ= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.3.0/go.mod h1:2LAuqPx1I6jNfaGDucWfA2zqQCYCOMCDHiCOciALyNw= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.0/go.mod h1:5E1J3/TTYy6z909QNR0QnXGBpfESYGDqd3O0zqONghU= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.9.0/go.mod h1:19SxQ+9zANyJCnNaoF3ovl8bFil4TaqCYEDdqNGKM+A= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.10.0/go.mod h1:I6/fHT/fH460v09eg2gVrd8B/IqskhNdpcLH0WNO3QI= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.11.0/go.mod h1:rwdUKJV5rm+vHu1ncD1iGDqahBEL8O0tBjVqo9eO2N0= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.7.1/go.mod h1:wN/mvkow08GauDwJ70jnzJ1e+hE+Q3Q7TwpYLXOe9oI= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.0/go.mod h1:NO3Q5ZTTQtO2xIg2+xTXYDiT7knSejfeDm7WGDaOo0U= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.3/go.mod h1:L72JSFj9OwHwyukeuKFFyTj6uFWE4AjB0IQp97bd9Lc= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.4/go.mod h1:XHgQ7Hz2WY2GAn//UXHofLfPXWh+s62MbMOijrg12Lw= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.5/go.mod h1:2hXc8ooJqF2nAznsbJQIn+7h851/bu8GVC80OVTTqf8= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.0/go.mod h1:anlUzBoEWglcUxUQwZA7HQOEVEnQALVZsizAapB2hq8= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.1.0/go.mod h1:KdVvdk4gb7iatuHZgIkIqvJlWHBtjCJLUtD/uO/FkWw= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.2.0/go.mod h1:BsCSJHx5DnDXIrOcqB8KN1/B+hXLG/bi4Y6Vjcx/x9E= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.3.0/go.mod h1:miRSv9l093jX/t/j+mBCaLqFHo9xKYzJ7DGm1BsGoJM= github.com/aws/aws-sdk-go-v2/internal/ini v1.1.1/go.mod h1:Zy8smImhTdOETZqfyn01iNOe0CNggVbPjCajyaz6Gvg= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.0/go.mod h1:6oXGy4GLpypD3uCh8wcqztigGgmhLToMfjavgh+VySg= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.3/go.mod h1:N4dv+zawriMFZBO/6UKg3zt+XO6xWOQo1neAA0lFbo4= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.4/go.mod h1:R3sWUqPcfXSiF/LSFJhjyJmpg9uV6yP2yv3YZZjldVI= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.5/go.mod h1:R3sWUqPcfXSiF/LSFJhjyJmpg9uV6yP2yv3YZZjldVI= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.6/go.mod h1:o1ippSg3yJx5EuT4AOGXJCUcmt5vrcxla1cg6K1Q8Iw= github.com/aws/aws-sdk-go-v2/service/ecr v1.4.1/go.mod h1:FglZcyeiBqcbvyinl+n14aT/EWC7S1MIH+Gan2iizt0= github.com/aws/aws-sdk-go-v2/service/ecr v1.13.0/go.mod h1:X9rkClmo0/dXh2fwvhkMoXR5zxirrzCqMgfU+Z0HIgs= github.com/aws/aws-sdk-go-v2/service/ecr v1.14.0/go.mod h1:a3WUi3JjM3MFtIYenSYPJ7UZPXsw7U7vzebnynxucks= +github.com/aws/aws-sdk-go-v2/service/ecr v1.15.0/go.mod h1:4zYI85WiYDhFaU1jPFVfkD7HlBcdnITDE3QxDwy4Kus= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.4.1/go.mod h1:eD5Eo4drVP2FLTw0G+SMIPWNWvQRGGTtIZR2XeAagoA= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.10.0/go.mod h1:wlxlU/f1AOpsYIxt86LyrztTAIhyp/6HRNHcZjLzHjg= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.11.0/go.mod h1:iurUYk+aG+E2DO0MnQEZKh9zsaIxuTcrvCaAUTUhuTU= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.12.0/go.mod h1:IArQ3IBR00FkuraKwudKZZU32OxJfdTdwV+W5iZh3Y4= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.5.0/go.mod h1:80NaCIH9YU3rzTTs/J/ECATjXuRqzo/wB6ukO6MZ0XY= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.2.1/go.mod h1:zceowr5Z1Nh2WVP8bf/3ikB41IZW59E4yIYbg+pC6mw= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.0/go.mod h1:Mq6AEc+oEjCUlBuLiK5YwW4shSOAKCQ3tXN0sQeYoBA= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.6.0/go.mod h1:wTgFkG6t7jS/6Y0SILXwfspV3IXowb6ngsAlSajW0Kc= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.7.0/go.mod h1:K/qPe6AP2TGYv4l6n7c88zh9jWBDf6nHhvg1fx/EWfU= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.8.0/go.mod h1:rBDLgXDAwHOfxZKLRDl8OGTPzFDC+a2pLqNNj8+QwfI= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.9.0/go.mod h1:xKCZ4YFSF2s4Hnb/J0TLeOsKuGzICzcElaOKNGrVnx4= github.com/aws/aws-sdk-go-v2/service/kms v1.10.0/go.mod h1:ZkHWL8m5Nw1g9yMXqpCjnIJtSDToAmNbXXZ9gj0bO7s= github.com/aws/aws-sdk-go-v2/service/s3 v1.19.0/go.mod h1:Gwz3aVctJe6mUY9T//bcALArPUaFmNAy2rTB9qN4No8= @@ -460,16 +478,20 @@ github.com/aws/aws-sdk-go-v2/service/sso v1.3.1/go.mod h1:J3A3RGUvuCZjvSuZEcOpHD github.com/aws/aws-sdk-go-v2/service/sso v1.6.0/go.mod h1:Q/l0ON1annSU+mc0JybDy1Gy6dnJxIcWjphO6qJPzvM= github.com/aws/aws-sdk-go-v2/service/sso v1.8.0/go.mod h1:AB6v3BedyhVRIbPQbJnUsBmtup2pFiikpp5n3YyB6Ac= github.com/aws/aws-sdk-go-v2/service/sso v1.9.0/go.mod h1:vCV4glupK3tR7pw7ks7Y4jYRL86VvxS+g5qk04YeWrU= +github.com/aws/aws-sdk-go-v2/service/sso v1.10.0/go.mod h1:m1CRRFX7eH3EE6w0ntdu+lo+Ph9VS7y8qRV/vdym0ZY= github.com/aws/aws-sdk-go-v2/service/sts v1.6.0/go.mod h1:q7o0j7d7HrJk/vr9uUt3BVRASvcU7gYZB9PUgPiByXg= github.com/aws/aws-sdk-go-v2/service/sts v1.10.0/go.mod h1:jLKCFqS+1T4i7HDqCP9GM4Uk75YW1cS0o82LdxpMyOE= github.com/aws/aws-sdk-go-v2/service/sts v1.13.0/go.mod h1:jQto17aC9pJ6xRa1g29uXZhbcS6qNT3PSnKfPShq4sY= github.com/aws/aws-sdk-go-v2/service/sts v1.14.0/go.mod h1:u0xMJKDvvfocRjiozsoZglVNXRG19043xzp3r2ivLIk= +github.com/aws/aws-sdk-go-v2/service/sts v1.15.0/go.mod h1:E264g2Gl5U9KTGzmd8ypGEAoh75VmqyuA/Ox5O1eRE4= github.com/aws/smithy-go v1.6.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/aws/smithy-go v1.9.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/aws/smithy-go v1.9.1/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/aws/smithy-go v1.10.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= +github.com/aws/smithy-go v1.11.0/go.mod h1:3xHYmszWVx2c0kIwQeEVf9uSm4fYZt67FBJnwub1bgM= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20211215200129-69c85dc22db6/go.mod h1:8vJsEZ4iRqG+Vx6pKhWK6U00qcj0KC37IsfszMkY6UE= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20220216180153-3d7835abdf40/go.mod h1:8vJsEZ4iRqG+Vx6pKhWK6U00qcj0KC37IsfszMkY6UE= +github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20220228164355-396b2034c795/go.mod h1:8vJsEZ4iRqG+Vx6pKhWK6U00qcj0KC37IsfszMkY6UE= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= @@ -510,6 +532,7 @@ github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQ github.com/breml/bidichk v0.1.1/go.mod h1:zbfeitpevDUGI7V91Uzzuwrn4Vls8MoBMrwtt78jmso= github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= @@ -533,6 +556,7 @@ github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0 h1:t/LhUZLVitR1Ow2YOnduCsavhwFUklBMoGVYUCqmCqk= @@ -565,9 +589,12 @@ github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudevents/conformance v0.2.0/go.mod h1:rHKDwylBH89Rns6U3wL9ww8bg9/4GbwRCDNuyoC6bcc= github.com/cloudevents/sdk-go/observability/opencensus/v2 v2.4.1/go.mod h1:lhEpxMrIUkeu9rVRgoAbyqZ8GR8Hd3DUy+thHUxAHoI= +github.com/cloudevents/sdk-go/sql/v2 v2.8.0 h1:gWednxJHL0Ycf93XeEFyQxYj81A7b4eNwkzjNxGunAM= +github.com/cloudevents/sdk-go/sql/v2 v2.8.0/go.mod h1:u9acNJbhmi1wnDJro4PEAqbr4N1LTCyEUClErxbPS1A= github.com/cloudevents/sdk-go/v2 v2.4.1/go.mod h1:MZiMwmAh5tGj+fPFvtHv9hKurKqXtdB9haJYMJ/7GJY= -github.com/cloudevents/sdk-go/v2 v2.5.0 h1:Ts6aLHbBUJfcNcZ4ouAfJ4+Np7SE1Yf2w4ADKRCd7Fo= github.com/cloudevents/sdk-go/v2 v2.5.0/go.mod h1:nlXhgFkf0uTopxmRXalyMwS2LG70cRGPrxzmjJgSG0U= +github.com/cloudevents/sdk-go/v2 v2.8.0 h1:kmRaLbsafZmidZ0rZ6h7WOMqCkRMcVTLV5lxV/HKQ9Y= +github.com/cloudevents/sdk-go/v2 v2.8.0/go.mod h1:GpCBmUj7DIRiDhVvsK5d6WCbgTWs8DxAWTRtAwQmIXs= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -600,8 +627,9 @@ github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1 github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.0.1 h1:iJnMvco9XGvKUvNQkv88bE4uJXxRQH18efbKo9w5vHQ= github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= +github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4= +github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= @@ -629,16 +657,18 @@ github.com/containerd/containerd v1.5.2/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTV github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s= github.com/containerd/containerd v1.5.9/go.mod h1:fvQqCfadDGga5HZyn3j4+dx56qj2I9YwBrlSdalvJYQ= -github.com/containerd/containerd v1.5.10 h1:3cQ2uRVCkJVcx5VombsE7105Gl9Wrl7ORAO3+4+ogf4= github.com/containerd/containerd v1.5.10/go.mod h1:fvQqCfadDGga5HZyn3j4+dx56qj2I9YwBrlSdalvJYQ= +github.com/containerd/containerd v1.6.0 h1:CLa12ZcV0d2ZTRKq1ssioeJpTnPJBMyndpEKA+UtzJg= +github.com/containerd/containerd v1.6.0/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= -github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8= github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/containerd/continuity v0.2.2 h1:QSqfxcn8c+12slxwu00AtzXrsami0MJb/MQs9lOLHLA= +github.com/containerd/continuity v0.2.2/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk= github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= @@ -648,6 +678,8 @@ github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O1 github.com/containerd/fuse-overlayfs-snapshotter v1.0.2/go.mod h1:nRZceC8a7dRm3Ao6cJAwuJWPFiBPaibHiFntRUnzhwU= github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= +github.com/containerd/go-cni v1.1.0/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA= +github.com/containerd/go-cni v1.1.3/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA= github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= @@ -657,6 +689,7 @@ github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= +github.com/containerd/imgcrypt v1.1.3/go.mod h1:/TPA1GIDXMzbj01yd8pIbQiLdQxed5ue1wb8bP7PQu4= github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= @@ -668,8 +701,9 @@ github.com/containerd/stargz-snapshotter/estargz v0.6.4/go.mod h1:83VWDqHnurTKli github.com/containerd/stargz-snapshotter/estargz v0.7.0/go.mod h1:83VWDqHnurTKliEB0YvWMiCfLDwv4Cjj1X9Vk98GJZw= github.com/containerd/stargz-snapshotter/estargz v0.10.0/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0= github.com/containerd/stargz-snapshotter/estargz v0.10.1/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0= -github.com/containerd/stargz-snapshotter/estargz v0.11.0 h1:t0IW5kOmY7AXDAWRUs2uVzDhijAUOAYVr/dyRhOQvBg= github.com/containerd/stargz-snapshotter/estargz v0.11.0/go.mod h1:/KsZXsJRllMbTKFfG0miFQWViQKdI9+9aSXs+HN0+ac= +github.com/containerd/stargz-snapshotter/estargz v0.11.1 h1:mNQqxcAWmDrV6d6yUvzFhfY8puNzoQz9v4diW+Pmei4= +github.com/containerd/stargz-snapshotter/estargz v0.11.1/go.mod h1:6VoPcf4M1wvnogWxqc4TqBWWErCS+R+ucnPZId2VbpQ= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= @@ -689,8 +723,10 @@ github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNR github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v1.0.1/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y= github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= +github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNBDZcxSOplJT5ico8/FLE= github.com/containers/image/v5 v5.19.1 h1:g4/+XIuh1kRoRn2MfLDhfHhkNOIO9JtqhSyo55tjpfE= github.com/containers/image/v5 v5.19.1/go.mod h1:ewoo3u+TpJvGmsz64XgzbyTHwHtM94q7mgK/pX+v2SE= github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY= @@ -706,6 +742,7 @@ github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-oidc/v3 v3.1.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpAm8MJMesvo= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -956,8 +993,11 @@ github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7 github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2 h1:ahHml/yUpnlb96Rp8HCvtYVPY8ZYpxq3g7UYchIYwbs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= @@ -1027,7 +1067,6 @@ github.com/go-openapi/spec v0.20.0/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFut github.com/go-openapi/spec v0.20.1/go.mod h1:93x7oh+d+FQsmsieroS4cmR3u0p/ywH649a3qwC9OsQ= github.com/go-openapi/spec v0.20.2/go.mod h1:RW6Xcbs6LOyWLU/mXGdzn2Qc+3aj+ASfI7rvSZh1Vls= github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg= -github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M= github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= @@ -1251,9 +1290,8 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/cel-go v0.7.3 h1:8v9BSN0avuGwrHFKNCjfiQ/CE6+D6sW+BDyOVoEeP6o= -github.com/google/cel-go v0.7.3/go.mod h1:4EtyFAHT5xNr0Msu0MJjyGxPUgdr9DlcaPyzLt/kkt8= -github.com/google/cel-spec v0.5.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA= +github.com/google/cel-go v0.11.2 h1:o16cOggWWtH1a3ZHQ8uWqt8nd255vDrEK1mDE1cFRSQ= +github.com/google/cel-go v0.11.2/go.mod h1:drz+knCRsctDZ180KZHwIEEUb9IdK/nxPoyhxi+O1K0= github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= github.com/google/certificate-transparency-go v1.1.1/go.mod h1:FDKqPvSXawb2ecErVRrD+nfy23RCzyl7eqVCEmlT1Zs= github.com/google/certificate-transparency-go v1.1.2-0.20210422104406-9f33727a7a18/go.mod h1:6CKh9dscIRoqc2kC6YUFICHZMT9NrClyPrRVFrdw1QQ= @@ -1286,21 +1324,24 @@ github.com/google/go-containerregistry v0.7.1-0.20211118220127-abdc633f8305/go.m github.com/google/go-containerregistry v0.7.1-0.20211203164431-c75901cce627/go.mod h1:IwJblnDNiCs8sxubbfPNniYsUqr8m+nt7YbPzecsGuE= github.com/google/go-containerregistry v0.8.0/go.mod h1:wW5v71NHGnQyb4k+gSshjxidrC7lN33MdWEn+Mz9TsI= github.com/google/go-containerregistry v0.8.1-0.20220110151055-a61fd0a8e2bb/go.mod h1:wW5v71NHGnQyb4k+gSshjxidrC7lN33MdWEn+Mz9TsI= +github.com/google/go-containerregistry v0.8.1-0.20220120151853-ac864e57b117/go.mod h1:wW5v71NHGnQyb4k+gSshjxidrC7lN33MdWEn+Mz9TsI= github.com/google/go-containerregistry v0.8.1-0.20220202214207-9c35968ef47e/go.mod h1:cwx3SjrH84Rh9VFJSIhPh43ovyOp3DCWgY3h8nWmdGQ= github.com/google/go-containerregistry v0.8.1-0.20220211173031-41f8d92709b7/go.mod h1:cwx3SjrH84Rh9VFJSIhPh43ovyOp3DCWgY3h8nWmdGQ= github.com/google/go-containerregistry v0.8.1-0.20220216220642-00c59d91847c/go.mod h1:MMbnwuvLeZJRPqhTs8jDWc8xGlOs5YCGx1TSc/qdExk= -github.com/google/go-containerregistry v0.8.1-0.20220219142810-1571d7fdc46e h1:1KGep3inUBSyCDbpk4noN5CfemOpEpQPPnN7UbBrdCU= -github.com/google/go-containerregistry v0.8.1-0.20220219142810-1571d7fdc46e/go.mod h1:MMbnwuvLeZJRPqhTs8jDWc8xGlOs5YCGx1TSc/qdExk= +github.com/google/go-containerregistry v0.8.1-0.20220414133640-f1b729141d33/go.mod h1:eTLvLZaEe2FoQsb25t7BLxQQryyrwHTzFfwxN87mhAw= +github.com/google/go-containerregistry v0.8.1-0.20220414143355-892d7a808387 h1:GWICy4b02s8EA1M9H5krRQ48BKpIHO5LtBBm2BQLhx0= +github.com/google/go-containerregistry v0.8.1-0.20220414143355-892d7a808387/go.mod h1:eTLvLZaEe2FoQsb25t7BLxQQryyrwHTzFfwxN87mhAw= github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20210610160139-c086c7f16d4e/go.mod h1:u9BUkrFoN0hojbyaW5occdRyQvT74KjJKx2VClbrDC8= github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20210918223331-0e8b581974dd/go.mod h1:j3IqhBG3Ox1NXmmhbWU4UmiHVAf2dUgB7le1Ch7JZQ0= -github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20211118220127-abdc633f8305/go.mod h1:/wxgGW8xlALyJwgyqAOe19EMFzNi+pePDhT33XMD1Yo= github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20211215180950-ab77ea68f600/go.mod h1:j3IqhBG3Ox1NXmmhbWU4UmiHVAf2dUgB7le1Ch7JZQ0= github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20220120151853-ac864e57b117/go.mod h1:BH7pLQnIZhfVpL7cRyWhvvz1bZLY9V45/HvXVh5UMDY= github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20220216220642-00c59d91847c/go.mod h1:m6nUV1MgElByyfWJCAKsEt+5s/BtU9ZLjyHDmoeAHcM= +github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20220414154538-570ba6c88a50/go.mod h1:m7mMYMlUraMy65yWp4AXkMgousS5LFPYcvI19yjz6W0= github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20220110151055-a61fd0a8e2bb/go.mod h1:SK4EqntTk6tHEyNngoqHUwjjZaW6mfzLukei4+cbvu8= github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20220120123041-d22850aca581/go.mod h1:SK4EqntTk6tHEyNngoqHUwjjZaW6mfzLukei4+cbvu8= github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20220128225446-c63684ed5f15/go.mod h1:juPcrnQFaTyH72YA4Lt2MwEFSGi3orvGXyzxzo+RLss= github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20220223122423-dd8d514a9b24/go.mod h1:MO/Ilc3XTxy/Pi8aMXEiRUl6icOqResFyhSFCLlqtR8= +github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20220414143355-892d7a808387/go.mod h1:QOryQrrP9Uq/1w9F7WOWWhK2/gHXg7F0i3J/hPG6yQA= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-github/v27 v27.0.6/go.mod h1:/0Gr8pJ55COkmv+S/yPKCczSkUPIM/LnFyubufRNIS0= github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM= @@ -1574,9 +1615,11 @@ github.com/influxdata/tdigest v0.0.0-20180711151920-a7d76c6f093a/go.mod h1:9Gkys github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= github.com/influxdata/tdigest v0.0.0-20191024211133-5d87a7585faa/go.mod h1:Z0kXnxzbTC2qrx4NaIzYkE1k66+6oEDQTvL95hQFh5Y= github.com/influxdata/tdigest v0.0.1/go.mod h1:Z0kXnxzbTC2qrx4NaIzYkE1k66+6oEDQTvL95hQFh5Y= +github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ= github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= +github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= @@ -1714,6 +1757,7 @@ github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8 github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.14.3/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.14.4 h1:eijASRJcobkVtSt81Olfh7JX43osYLwy5krOJo6YEu4= github.com/klauspost/compress v1.14.4/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= @@ -1916,7 +1960,9 @@ github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2J github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI= github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= +github.com/moby/sys/signal v0.6.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= +github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/moby/term v0.0.0-20200915141129-7f0af18e79f2/go.mod h1:TjQg8pa4iejrUrjiz0MCtMV38jdMNW4doKSiBrEvCQQ= github.com/moby/term v0.0.0-20201110203204-bea5bbe245bf/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= @@ -1994,6 +2040,7 @@ github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= @@ -2012,6 +2059,7 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= github.com/onsi/gomega v1.10.4/go.mod h1:g/HbgYopi++010VEqkFgJHKC09uJiW9UkXvMUuKHUCQ= +github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= @@ -2260,6 +2308,7 @@ github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIH github.com/sabhiram/go-gitignore v0.0.0-20201211074657-223ce5d391b0 h1:4Q/TASkyjpqyR5DL5+6c2FGSDpHM5bTMSspcXr7J6R8= github.com/sabhiram/go-gitignore v0.0.0-20201211074657-223ce5d391b0/go.mod h1:b18R55ulyQ/h3RaWyloPyER7fWQVZvimKKhnI5OfrJQ= github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= +github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/sagikazarmark/crypt v0.1.0/go.mod h1:B/mN0msZuINBtQ1zZLEQcegFJJf9vnYIR88KRMEuODE= github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= github.com/sagikazarmark/crypt v0.4.0/go.mod h1:ALv2SRj7GxYV4HO9elxH9nS6M9gW+xDNxqmyJ6RfDFM= @@ -2269,6 +2318,7 @@ github.com/sassoftware/go-rpmutils v0.0.0-20190420191620-a8f1baeba37b/go.mod h1: github.com/sassoftware/go-rpmutils v0.1.1/go.mod h1:euhXULoBpvAxqrBHEyJS4Tsu3hHxUmQWNymxoJbzgUY= github.com/sassoftware/relic v0.0.0-20210427151427-dfb082b79b74/go.mod h1:YlB8wFIZmFLZ1JllNBfSURzz52fBxbliNgYALk1UDmk= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8= github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM= @@ -2487,6 +2537,7 @@ github.com/tsenart/go-tsz v0.0.0-20180814235614-0bd30b3df1c3/go.mod h1:SWZznP1z5 github.com/tsenart/vegeta v12.7.1-0.20190725001342-b5f4fca92137+incompatible/go.mod h1:Smz/ZWfhKRcyDDChZkG3CyTHdj87lHzio/HOCkbndXM= github.com/tsenart/vegeta/v12 v12.8.4/go.mod h1:ZiJtwLn/9M4fTPdMY7bdbIeyNeFVE8/AHbWFqCsUuho= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= @@ -2528,9 +2579,11 @@ github.com/viki-org/dnscache v0.0.0-20130720023526-c70c1f23c5d8/go.mod h1:dniwbG github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/wavesoftware/go-ensure v1.0.0/go.mod h1:K2UAFSwMTvpiRGay/M3aEYYuurcR8S4A6HkQlJPV8k4= github.com/whilp/git-urls v1.0.0 h1:95f6UMWN5FKW71ECsXRUd3FVYiXdrE7aX4NZKcPmIjU= @@ -2653,17 +2706,23 @@ go.opentelemetry.io/contrib v0.21.0/go.mod h1:EH4yDYeNoaTqn/8yCWQmfNB78VHfGX2Jt2 go.opentelemetry.io/contrib v1.3.0/go.mod h1:FlyPNX9s4U6MCsWEc5YAK4KzKNHFDsjrDUZijJiXvy8= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.21.0/go.mod h1:Vm5u/mtkj1OMhtao0v+BGo2LUoLCgHYXvRmj0jWITlE= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0/go.mod h1:vEhqr0m4eTc+DWxfsXoXue2GBgV2uUwVznkGIHW/e5w= go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.21.0/go.mod h1:a9cocRplhIBkUAJmak+BPDx+LVL7cTmqUPB0uBcTA4k= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.21.0/go.mod h1:JQAtechjxLEL81EjmbRwxBq/XEzGaHcsPuDHAx54hg4= go.opentelemetry.io/otel v0.16.0/go.mod h1:e4GKElweB8W2gWUqbghw0B8t5MCTccc9212eNHnOHwA= go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= +go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= go.opentelemetry.io/otel/exporters/jaeger v1.0.0-RC1/go.mod h1:FXJnjGCoTQL6nQ8OpFJ0JI1DrdOvMoVx49ic0Hg4+D4= go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.0-RC1/go.mod h1:FliQjImlo7emZVjixV8nbDMAa4iAkcWTE9zzSEOiEPw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.0-RC1/go.mod h1:cDwRc2Jrh5Gku1peGK8p9rRuX/Uq2OtVmLicjlw2WYU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0/go.mod h1:keUU7UfnwWTWpJ+FWnyqmogPa82nuU5VUANFq49hlMY= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.0.0-RC1/go.mod h1:OYKzEoxgXFvehW7X12WYT4/a2BlASJK9l7RtG4A91fg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0/go.mod h1:QNX1aly8ehqqX1LEa6YniTU7VY9I6R3X/oPxhGdTceE= go.opentelemetry.io/otel/internal/metric v0.21.0/go.mod h1:iOfAaY2YycsXfYD4kaRSbLx2LKmfpKObWBEv9QK5zFo= go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= go.opentelemetry.io/otel/metric v0.21.0/go.mod h1:JWCt1bjivC4iCrz/aCrM1GSw+ZcvY44KCbaeeRhzHnc= @@ -2671,10 +2730,12 @@ go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4= go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= go.opentelemetry.io/otel/sdk v1.0.0-RC1/go.mod h1:kj6yPn7Pgt5ByRuwesbaWcRLA+V7BSDg3Hf8xRvsvf8= +go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg= +go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ= @@ -3119,6 +3180,8 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -3171,8 +3234,9 @@ golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs= +golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/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-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -3392,8 +3456,9 @@ google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFd google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= google.golang.org/api v0.64.0/go.mod h1:931CdxA8Rm4t6zqTFGSsgwbAEZ2+GMYurbndwSimebM= google.golang.org/api v0.65.0/go.mod h1:ArYhxgGadlWmqO1IqVujw6Cs8IdD33bTmzKo2Sh+cbg= -google.golang.org/api v0.67.0 h1:lYaaLa+x3VVUhtosaK9xihwQ9H9KRa557REHwwZ2orM= google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0 h1:67zQnAE0T2rB0A3CwLSas0K+SbVzSxP+zTLkQLexeiw= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -3457,7 +3522,6 @@ google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200929141702-51c3e5b607fe/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201102152239-715cce707fb0/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -3517,8 +3581,12 @@ google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220303160752-862486edd9cc h1:fb/ViRpv3ln/LvbqZtTpoOd1YQDNH12gaGZreoSFovE= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220301145929-1ac2ace0dbf7/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220303160752-862486edd9cc/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6 h1:FglFEfyj61zP3c6LgjmVHxYxZWXYul9oiS1EZqD5gLc= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= @@ -3697,8 +3765,9 @@ k8s.io/apiserver v0.20.7/go.mod h1:7gbB7UjDdP1/epYBGnIUE6jWY4Wpz99cZ7igfDa9rv4= k8s.io/apiserver v0.21.0/go.mod h1:w2YSn4/WIwYuxG5zJmcqtRdtqgW/J2JRgFAqps3bBpg= k8s.io/apiserver v0.21.4/go.mod h1:SErUuFBBPZUcD2nsUU8hItxoYheqyYr2o/pCINEPW8g= k8s.io/apiserver v0.22.5/go.mod h1:s2WbtgZAkTKt679sYtSudEQrTGWUSQAPe6MupLnlmaQ= -k8s.io/cli-runtime v0.21.4 h1:kvOzx6dKg+9wRuHTzSqo8tfTV6ixZCkmi+ag54s7mn8= k8s.io/cli-runtime v0.21.4/go.mod h1:eRbLHYkdVWzvG87yrkgGd8CqX6/+fAG9DTdAqTXmlRY= +k8s.io/cli-runtime v0.22.5 h1:bZqLgx1INiPgXyMk/Hu3o5NFmdfvlvtsoE+wHJuKA2U= +k8s.io/cli-runtime v0.22.5/go.mod h1:12ah4O0kaevIYHsRcFGt8RKER0wlTN2yCgHp1c4Uxp4= k8s.io/client-go v0.22.5 h1:I8Zn/UqIdi2r02aZmhaJ1hqMxcpfJ3t5VqvHtctHYFo= k8s.io/client-go v0.22.5/go.mod h1:cs6yf/61q2T1SdQL5Rdcjg9J1ElXSwbjSrW2vFImM4Y= k8s.io/cloud-provider v0.17.4/go.mod h1:XEjKDzfD+b9MTLXQFlDGkk6Ho8SGMpaU8Uugx/KNK9U= @@ -3723,6 +3792,7 @@ k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= +k8s.io/cri-api v0.23.1/go.mod h1:REJE3PSU0h/LOV1APBrupxrEJqnoxZC8KWzkBUHwrK4= k8s.io/csi-translation-lib v0.17.4/go.mod h1:CsxmjwxEI0tTNMzffIAcgR9lX4wOh6AKHdxQrT7L0oo= k8s.io/csi-translation-lib v0.19.7/go.mod h1:WghizPQuzuygr2WdpgN2EjcNpDD2V4EAbxFXsgHgSBk= k8s.io/csi-translation-lib v0.21.0/go.mod h1:edq+UMpgqEx3roTuGF/03uIuSOsI986jtu65+ytLlkA= @@ -3756,6 +3826,7 @@ k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= k8s.io/kube-openapi v0.0.0-20210113233702-8566a335510f/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= +k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= k8s.io/kube-openapi v0.0.0-20220114203427-a0453230fd26/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= @@ -3778,37 +3849,39 @@ k8s.io/utils v0.0.0-20220127004650-9b3446523e65/go.mod h1:jPW/WVKK9YHAvNhRxK0md/ k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= knative.dev/caching v0.0.0-20210803185815-4e553d2275a0/go.mod h1:Vs+HND39+KKaIQp9M3m3Jmt4YtznpitDQ3n53gxbDYQ= -knative.dev/caching v0.0.0-20211206133228-c29dc56d8f03/go.mod h1:xki+LBTL1riXSoU2dKznqUfgOlQ2eO/F1WF+GMXxH0k= -knative.dev/client v0.28.0 h1:x+wghPn3tZ/rPf7gsBcEro43Ev4zSwq91NGfNi/7lPI= -knative.dev/client v0.28.0/go.mod h1:QcPrTsTdc/3sGKugtjL9yYyTwcNvD5Su/KHltFVLlJ0= +knative.dev/caching v0.0.0-20220118175933-0c1cc094a7f4/go.mod h1:OHsK3XaWmdi2/mPaNBiX8LbefbtM6TptnT90eVbYGSA= +knative.dev/client v0.29.0 h1:VzmXYWNfzF5O1OUpCYv2rd8hj6Q3mwGNwOyx6y4G0g8= +knative.dev/client v0.29.0/go.mod h1:VaTZlNkplns4UrscGPp4CwKcIVRcfC4Po1yRvfF4JiQ= knative.dev/eventing v0.25.0/go.mod h1:8jIsrnSONPgv+m63OTzpwZQJiQASYl77C3llCyYlBMU= -knative.dev/eventing v0.28.0/go.mod h1:zxoB37kQxEkfCvKA7wZuHOPYInz6SFJzrhmG9IAd/iY= -knative.dev/eventing v0.28.4 h1:frHm4zNcJaAfA1m11pn+ueyAyqQOSmy5j9I4dpf2c0M= -knative.dev/eventing v0.28.4/go.mod h1:zxoB37kQxEkfCvKA7wZuHOPYInz6SFJzrhmG9IAd/iY= +knative.dev/eventing v0.29.0/go.mod h1:u5T5NZTDUsLR7yJwp5MDnBnDX5MhywD3yK3Rq+7gTtI= +knative.dev/eventing v0.29.2-0.20220420140829-ce4fe0990d23 h1:9DucdcOalX90T2QMhQjh4MLjXUEgqgsRxuK1o1Tt+44= +knative.dev/eventing v0.29.2-0.20220420140829-ce4fe0990d23/go.mod h1:u5T5NZTDUsLR7yJwp5MDnBnDX5MhywD3yK3Rq+7gTtI= knative.dev/hack v0.0.0-20210622141627-e28525d8d260/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI= knative.dev/hack v0.0.0-20211122162614-813559cefdda/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI= knative.dev/hack v0.0.0-20211203062838-e11ac125e707/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI= +knative.dev/hack v0.0.0-20220118141833-9b2ed8471e30/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI= knative.dev/hack v0.0.0-20220128200847-51a42b2eb63e h1:pW3LMToyFhAhbHQWQwUHLY57i7gjvyFwFC8Sg6oNkJ8= knative.dev/hack v0.0.0-20220128200847-51a42b2eb63e/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI= knative.dev/hack/schema v0.0.0-20210622141627-e28525d8d260/go.mod h1:ffjwmdcrH5vN3mPhO8RrF2KfNnbHeCE2C60A+2cv3U0= -knative.dev/hack/schema v0.0.0-20211203062838-e11ac125e707/go.mod h1:ffjwmdcrH5vN3mPhO8RrF2KfNnbHeCE2C60A+2cv3U0= +knative.dev/hack/schema v0.0.0-20220118141833-9b2ed8471e30/go.mod h1:ffjwmdcrH5vN3mPhO8RrF2KfNnbHeCE2C60A+2cv3U0= knative.dev/networking v0.0.0-20210803181815-acdfd41c575c/go.mod h1:UA9m1M3rGssy63gVwjSh7CYoWTKZNO8cnY9QsIu7tyo= -knative.dev/networking v0.0.0-20211209101835-8ef631418fc0/go.mod h1:+ozCw7PVf//G9+HOW04hfWnU8UJE5fmWAQkb+ieMaXY= +knative.dev/networking v0.0.0-20220120043934-ec785540a732/go.mod h1:6cKBV/h/vIQWCPOkds/RvzUmMR8Vz6Dks2NWb0+3xks= knative.dev/networking v0.0.0-20220120045035-ec849677a316 h1:fHgHP3nnJSfq115RgTMYVHPQBsBKQYtjUVGhMT/VLaA= knative.dev/networking v0.0.0-20220120045035-ec849677a316/go.mod h1:+ozCw7PVf//G9+HOW04hfWnU8UJE5fmWAQkb+ieMaXY= knative.dev/pkg v0.0.0-20210803160015-21eb4c167cc5/go.mod h1:RPk5txNA3apR9X40D4MpUOP9/VqOG8CrtABWfOwGVS4= knative.dev/pkg v0.0.0-20211206113427-18589ac7627e/go.mod h1:E6B4RTjZyxe55a0kxOlnEHEl71zuG7gghnqYvNBKwBw= knative.dev/pkg v0.0.0-20211215065729-552319d4f55b/go.mod h1:hrD91/shO1o4KMZa4oWhnbRPmVJhvq86TLy/STF/qf8= knative.dev/pkg v0.0.0-20220104185830-52e42b760b54/go.mod h1:189cvGP0mwpqwZGFrLk5WuERIsNI/J6HuQ1CIX7SXxY= +knative.dev/pkg v0.0.0-20220118160532-77555ea48cd4/go.mod h1:etVT7Tm8pSDf4RKhGk4r7j/hj3dNBpvT7bO6a6wpahs= knative.dev/pkg v0.0.0-20220131144930-f4b57aef0006/go.mod h1:bZMFTPDPHV3wXuiQ09UJuEGYYQnfpe81MCxNvsMAiJk= -knative.dev/pkg v0.0.0-20220222214539-0b8a9403de7e h1:+5xPVmp1aajA1z1BxGmUrPLj8y0GEDdHh0y+YTi8XHk= -knative.dev/pkg v0.0.0-20220222214539-0b8a9403de7e/go.mod h1:E6B4RTjZyxe55a0kxOlnEHEl71zuG7gghnqYvNBKwBw= +knative.dev/pkg v0.0.0-20220222214439-083dd97300e1 h1:p6MI/Rs9AZC5+qRvqX48njRjmFBYi4Y80q23efgJ+38= +knative.dev/pkg v0.0.0-20220222214439-083dd97300e1/go.mod h1:etVT7Tm8pSDf4RKhGk4r7j/hj3dNBpvT7bO6a6wpahs= knative.dev/reconciler-test v0.0.0-20210803183715-b61cc77c06f6/go.mod h1:+Kovy+G5zXZNcuO/uB+zfo37vFKZzsLIlWezt/nKMz0= -knative.dev/reconciler-test v0.0.0-20211207070557-0d138a88867b/go.mod h1:dCq1Fuu+eUISdnxABMvoDhefF91DYwE6O3rTYTraXbw= +knative.dev/reconciler-test v0.0.0-20220118183433-c8bfbe66bada/go.mod h1:XV4cghzCtdASkfUsfMYSnGfGRyd/naDjy9h7Tnae22g= knative.dev/serving v0.25.0/go.mod h1:24E4fVyViFnz8aAaafzdrYKB7CAsQr4FMU7QXoIE6CI= -knative.dev/serving v0.28.0/go.mod h1:1d8YYUu0hY19KlIRs2SgAn/o64Hr265+3fhOtV3FFVA= -knative.dev/serving v0.28.4 h1:745+sWSEaSxDVpKXqmPVaKb4nzo1n8W6cw++TCvHD3U= -knative.dev/serving v0.28.4/go.mod h1:jTq5OY/B4PazjfQI5MjTMEDdZgxlWRXA7qIU8FrDwSU= +knative.dev/serving v0.29.0/go.mod h1:8Ay9QjyTcqoJE+2PietSmT5/VMdSQHe5aIBhsAFOCjM= +knative.dev/serving v0.29.5 h1:+NUjm2Npo43hWlQTkGsG89johEzIf9aiMKUsKfidzjA= +knative.dev/serving v0.29.5/go.mod h1:00SLmEVPRwqtDPu4dXn2L8BVyvILurecO1z/v6oDAg0= modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= @@ -3831,10 +3904,12 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyz sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= -sigs.k8s.io/kustomize/api v0.8.8 h1:G2z6JPSSjtWWgMeWSoHdXqyftJNmMmyxXpwENGoOtGE= sigs.k8s.io/kustomize/api v0.8.8/go.mod h1:He1zoK0nk43Pc6NlV085xDXDXTNprtcyKZVm3swsdNY= -sigs.k8s.io/kustomize/kyaml v0.10.17 h1:4zrV0ym5AYa0e512q7K3Wp1u7mzoWW0xR3UHJcGWGIg= +sigs.k8s.io/kustomize/api v0.8.11 h1:LzQzlq6Z023b+mBtc6v72N2mSHYmN8x7ssgbf/hv0H8= +sigs.k8s.io/kustomize/api v0.8.11/go.mod h1:a77Ls36JdfCWojpUqR6m60pdGY1AYFix4AH83nJtY1g= sigs.k8s.io/kustomize/kyaml v0.10.17/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg= +sigs.k8s.io/kustomize/kyaml v0.11.0 h1:9KhiCPKaVyuPcgOLJXkvytOvjMJLoxpjodiycb4gHsA= +sigs.k8s.io/kustomize/kyaml v0.11.0/go.mod h1:GNMwjim4Ypgp/MueD3zXHLRJEjz7RvtPae0AwlvEMFM= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06 h1:zD2IemQ4LmOcAumeiyDWXKUI2SO0NYDe3H6QGvPOVgU= sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18= diff --git a/third_party/VENDOR-LICENSE/github.com/antlr/antlr4/runtime/Go/antlr/LICENSE b/third_party/VENDOR-LICENSE/github.com/antlr/antlr4/runtime/Go/antlr/LICENSE new file mode 100644 index 000000000..52cf18e42 --- /dev/null +++ b/third_party/VENDOR-LICENSE/github.com/antlr/antlr4/runtime/Go/antlr/LICENSE @@ -0,0 +1,26 @@ +Copyright 2021 The ANTLR Project + +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. diff --git a/third_party/VENDOR-LICENSE/github.com/antlr/antlr4/runtime/Go/antlr/LICENSE.txt b/third_party/VENDOR-LICENSE/github.com/antlr/antlr4/runtime/Go/antlr/LICENSE.txt deleted file mode 100644 index 2042d1bda..000000000 --- a/third_party/VENDOR-LICENSE/github.com/antlr/antlr4/runtime/Go/antlr/LICENSE.txt +++ /dev/null @@ -1,52 +0,0 @@ -[The "BSD 3-clause license"] -Copyright (c) 2012-2017 The ANTLR Project. 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 AUTHOR ``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 AUTHOR 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. - -===== - -MIT License for codepointat.js from https://git.io/codepointat -MIT License for fromcodepoint.js from https://git.io/vDW1m - -Copyright Mathias Bynens - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/go-openapi/spec/LICENSE b/third_party/VENDOR-LICENSE/github.com/cloudevents/sdk-go/sql/v2/LICENSE similarity index 99% rename from vendor/github.com/go-openapi/spec/LICENSE rename to third_party/VENDOR-LICENSE/github.com/cloudevents/sdk-go/sql/v2/LICENSE index d64569567..261eeb9e9 100644 --- a/vendor/github.com/go-openapi/spec/LICENSE +++ b/third_party/VENDOR-LICENSE/github.com/cloudevents/sdk-go/sql/v2/LICENSE @@ -1,4 +1,3 @@ - Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ diff --git a/third_party/VENDOR-LICENSE/github.com/google/cel-go/LICENSE b/third_party/VENDOR-LICENSE/github.com/google/cel-go/LICENSE index d64569567..2493ed2eb 100644 --- a/third_party/VENDOR-LICENSE/github.com/google/cel-go/LICENSE +++ b/third_party/VENDOR-LICENSE/github.com/google/cel-go/LICENSE @@ -200,3 +200,34 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + +=========================================================================== +The common/types/pb/equal.go modification of proto.Equal logic +=========================================================================== +Copyright (c) 2018 The Go 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: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of Google Inc. 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 +OWNER 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. diff --git a/third_party/VENDOR-LICENSE/k8s.io/klog/LICENSE b/third_party/VENDOR-LICENSE/k8s.io/klog/LICENSE deleted file mode 100644 index 37ec93a14..000000000 --- a/third_party/VENDOR-LICENSE/k8s.io/klog/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ -Apache License -Version 2.0, January 2004 -http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - -"License" shall mean the terms and conditions for use, reproduction, and -distribution as defined by Sections 1 through 9 of this document. - -"Licensor" shall mean the copyright owner or entity authorized by the copyright -owner that is granting the License. - -"Legal Entity" shall mean the union of the acting entity and all other entities -that control, are controlled by, or are under common control with that entity. -For the purposes of this definition, "control" means (i) the power, direct or -indirect, to cause the direction or management of such entity, whether by -contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the -outstanding shares, or (iii) beneficial ownership of such entity. - -"You" (or "Your") shall mean an individual or Legal Entity exercising -permissions granted by this License. - -"Source" form shall mean the preferred form for making modifications, including -but not limited to software source code, documentation source, and configuration -files. - -"Object" form shall mean any form resulting from mechanical transformation or -translation of a Source form, including but not limited to compiled object code, -generated documentation, and conversions to other media types. - -"Work" shall mean the work of authorship, whether in Source or Object form, made -available under the License, as indicated by a copyright notice that is included -in or attached to the work (an example is provided in the Appendix below). - -"Derivative Works" shall mean any work, whether in Source or Object form, that -is based on (or derived from) the Work and for which the editorial revisions, -annotations, elaborations, or other modifications represent, as a whole, an -original work of authorship. For the purposes of this License, Derivative Works -shall not include works that remain separable from, or merely link (or bind by -name) to the interfaces of, the Work and Derivative Works thereof. - -"Contribution" shall mean any work of authorship, including the original version -of the Work and any modifications or additions to that Work or Derivative Works -thereof, that is intentionally submitted to Licensor for inclusion in the Work -by the copyright owner or by an individual or Legal Entity authorized to submit -on behalf of the copyright owner. For the purposes of this definition, -"submitted" means any form of electronic, verbal, or written communication sent -to the Licensor or its representatives, including but not limited to -communication on electronic mailing lists, source code control systems, and -issue tracking systems that are managed by, or on behalf of, the Licensor for -the purpose of discussing and improving the Work, but excluding communication -that is conspicuously marked or otherwise designated in writing by the copyright -owner as "Not a Contribution." - -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf -of whom a Contribution has been received by Licensor and subsequently -incorporated within the Work. - -2. Grant of Copyright License. - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable copyright license to reproduce, prepare Derivative Works of, -publicly display, publicly perform, sublicense, and distribute the Work and such -Derivative Works in Source or Object form. - -3. Grant of Patent License. - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable (except as stated in this section) patent license to make, have -made, use, offer to sell, sell, import, and otherwise transfer the Work, where -such license applies only to those patent claims licensable by such Contributor -that are necessarily infringed by their Contribution(s) alone or by combination -of their Contribution(s) with the Work to which such Contribution(s) was -submitted. If You institute patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the Work or a -Contribution incorporated within the Work constitutes direct or contributory -patent infringement, then any patent licenses granted to You under this License -for that Work shall terminate as of the date such litigation is filed. - -4. Redistribution. - -You may reproduce and distribute copies of the Work or Derivative Works thereof -in any medium, with or without modifications, and in Source or Object form, -provided that You meet the following conditions: - -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -You must retain, in the Source form of any Derivative Works that You distribute, -all copyright, patent, trademark, and attribution notices from the Source form -of the Work, excluding those notices that do not pertain to any part of the -Derivative Works; and -If the Work includes a "NOTICE" text file as part of its distribution, then any -Derivative Works that You distribute must include a readable copy of the -attribution notices contained within such NOTICE file, excluding those notices -that do not pertain to any part of the Derivative Works, in at least one of the -following places: within a NOTICE text file distributed as part of the -Derivative Works; within the Source form or documentation, if provided along -with the Derivative Works; or, within a display generated by the Derivative -Works, if and wherever such third-party notices normally appear. The contents of -the NOTICE file are for informational purposes only and do not modify the -License. You may add Your own attribution notices within Derivative Works that -You distribute, alongside or as an addendum to the NOTICE text from the Work, -provided that such additional attribution notices cannot be construed as -modifying the License. -You may add Your own copyright statement to Your modifications and may provide -additional or different license terms and conditions for use, reproduction, or -distribution of Your modifications, or for any such Derivative Works as a whole, -provided Your use, reproduction, and distribution of the Work otherwise complies -with the conditions stated in this License. - -5. Submission of Contributions. - -Unless You explicitly state otherwise, any Contribution intentionally submitted -for inclusion in the Work by You to the Licensor shall be under the terms and -conditions of this License, without any additional terms or conditions. -Notwithstanding the above, nothing herein shall supersede or modify the terms of -any separate license agreement you may have executed with Licensor regarding -such Contributions. - -6. Trademarks. - -This License does not grant permission to use the trade names, trademarks, -service marks, or product names of the Licensor, except as required for -reasonable and customary use in describing the origin of the Work and -reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. - -Unless required by applicable law or agreed to in writing, Licensor provides the -Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, -including, without limitation, any warranties or conditions of TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are -solely responsible for determining the appropriateness of using or -redistributing the Work and assume any risks associated with Your exercise of -permissions under this License. - -8. Limitation of Liability. - -In no event and under no legal theory, whether in tort (including negligence), -contract, or otherwise, unless required by applicable law (such as deliberate -and grossly negligent acts) or agreed to in writing, shall any Contributor be -liable to You for damages, including any direct, indirect, special, incidental, -or consequential damages of any character arising as a result of this License or -out of the use or inability to use the Work (including but not limited to -damages for loss of goodwill, work stoppage, computer failure or malfunction, or -any and all other commercial damages or losses), even if such Contributor has -been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. - -While redistributing the Work or Derivative Works thereof, You may choose to -offer, and charge a fee for, acceptance of support, warranty, indemnity, or -other liability obligations and/or rights consistent with this License. However, -in accepting such obligations, You may act only on Your own behalf and on Your -sole responsibility, not on behalf of any other Contributor, and only if You -agree to indemnify, defend, and hold each Contributor harmless for any liability -incurred by, or claims asserted against, such Contributor by reason of your -accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work - -To apply the Apache License to your work, attach the following boilerplate -notice, with the fields enclosed by brackets "[]" replaced with your own -identifying information. (Don't include the brackets!) The text should be -enclosed in the appropriate comment syntax for the file format. We also -recommend that a file or class name and description of purpose be included on -the same "printed page" as the copyright notice for easier identification within -third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/third_party/VENDOR-LICENSE/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/LICENSE b/third_party/VENDOR-LICENSE/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/LICENSE new file mode 100644 index 000000000..2683e4bb1 --- /dev/null +++ b/third_party/VENDOR-LICENSE/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/LICENSE @@ -0,0 +1,50 @@ + +This project is covered by two different licenses: MIT and Apache. + +#### MIT License #### + +The following files were ported to Go from C files of libyaml, and thus +are still covered by their original MIT license, with the additional +copyright staring in 2011 when the project was ported over: + + apic.go emitterc.go parserc.go readerc.go scannerc.go + writerc.go yamlh.go yamlprivateh.go + +Copyright (c) 2006-2010 Kirill Simonov +Copyright (c) 2006-2011 Kirill Simonov + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +### Apache License ### + +All the remaining project files are covered by the Apache license: + +Copyright (c) 2011-2019 Canonical Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/third_party/VENDOR-LICENSE/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/NOTICE b/third_party/VENDOR-LICENSE/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/NOTICE new file mode 100644 index 000000000..866d74a7a --- /dev/null +++ b/third_party/VENDOR-LICENSE/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/NOTICE @@ -0,0 +1,13 @@ +Copyright 2011-2016 Canonical Ltd. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/github.com/Microsoft/go-winio/file.go b/vendor/github.com/Microsoft/go-winio/file.go index 0385e4108..293ab54c8 100644 --- a/vendor/github.com/Microsoft/go-winio/file.go +++ b/vendor/github.com/Microsoft/go-winio/file.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package winio @@ -143,6 +144,11 @@ func (f *win32File) Close() error { return nil } +// IsClosed checks if the file has been closed +func (f *win32File) IsClosed() bool { + return f.closing.isSet() +} + // prepareIo prepares for a new IO operation. // The caller must call f.wg.Done() when the IO is finished, prior to Close() returning. func (f *win32File) prepareIo() (*ioOperation, error) { diff --git a/vendor/github.com/Microsoft/go-winio/go.mod b/vendor/github.com/Microsoft/go-winio/go.mod index 98a8dea0e..f39a608da 100644 --- a/vendor/github.com/Microsoft/go-winio/go.mod +++ b/vendor/github.com/Microsoft/go-winio/go.mod @@ -1,9 +1,8 @@ module github.com/Microsoft/go-winio -go 1.12 +go 1.13 require ( - github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.7.0 golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c ) diff --git a/vendor/github.com/Microsoft/go-winio/go.sum b/vendor/github.com/Microsoft/go-winio/go.sum index aa6ad3b57..9bdcd9cfd 100644 --- a/vendor/github.com/Microsoft/go-winio/go.sum +++ b/vendor/github.com/Microsoft/go-winio/go.sum @@ -1,14 +1,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/github.com/Microsoft/go-winio/hvsock.go b/vendor/github.com/Microsoft/go-winio/hvsock.go index b632f8f8b..b2b644d00 100644 --- a/vendor/github.com/Microsoft/go-winio/hvsock.go +++ b/vendor/github.com/Microsoft/go-winio/hvsock.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package winio @@ -252,15 +253,23 @@ func (conn *HvsockConn) Close() error { return conn.sock.Close() } +func (conn *HvsockConn) IsClosed() bool { + return conn.sock.IsClosed() +} + func (conn *HvsockConn) shutdown(how int) error { - err := syscall.Shutdown(conn.sock.handle, syscall.SHUT_RD) + if conn.IsClosed() { + return ErrFileClosed + } + + err := syscall.Shutdown(conn.sock.handle, how) if err != nil { return os.NewSyscallError("shutdown", err) } return nil } -// CloseRead shuts down the read end of the socket. +// CloseRead shuts down the read end of the socket, preventing future read operations. func (conn *HvsockConn) CloseRead() error { err := conn.shutdown(syscall.SHUT_RD) if err != nil { @@ -269,8 +278,8 @@ func (conn *HvsockConn) CloseRead() error { return nil } -// CloseWrite shuts down the write end of the socket, notifying the other endpoint that -// no more data will be written. +// CloseWrite shuts down the write end of the socket, preventing future write operations and +// notifying the other endpoint that no more data will be written. func (conn *HvsockConn) CloseWrite() error { err := conn.shutdown(syscall.SHUT_WR) if err != nil { diff --git a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go index f497c0e39..2d9161e2d 100644 --- a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go +++ b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go @@ -14,8 +14,6 @@ import ( "encoding/binary" "fmt" "strconv" - - "golang.org/x/sys/windows" ) // Variant specifies which GUID variant (or "type") of the GUID. It determines @@ -41,13 +39,6 @@ type Version uint8 var _ = (encoding.TextMarshaler)(GUID{}) var _ = (encoding.TextUnmarshaler)(&GUID{}) -// GUID represents a GUID/UUID. It has the same structure as -// golang.org/x/sys/windows.GUID so that it can be used with functions expecting -// that type. It is defined as its own type so that stringification and -// marshaling can be supported. The representation matches that used by native -// Windows code. -type GUID windows.GUID - // NewV4 returns a new version 4 (pseudorandom) GUID, as defined by RFC 4122. func NewV4() (GUID, error) { var b [16]byte diff --git a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go new file mode 100644 index 000000000..f64d828c0 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go @@ -0,0 +1,15 @@ +// +build !windows + +package guid + +// GUID represents a GUID/UUID. It has the same structure as +// golang.org/x/sys/windows.GUID so that it can be used with functions expecting +// that type. It is defined as its own type as that is only available to builds +// targeted at `windows`. The representation matches that used by native Windows +// code. +type GUID struct { + Data1 uint32 + Data2 uint16 + Data3 uint16 + Data4 [8]byte +} diff --git a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go new file mode 100644 index 000000000..83617f4ee --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go @@ -0,0 +1,10 @@ +package guid + +import "golang.org/x/sys/windows" + +// GUID represents a GUID/UUID. It has the same structure as +// golang.org/x/sys/windows.GUID so that it can be used with functions expecting +// that type. It is defined as its own type so that stringification and +// marshaling can be supported. The representation matches that used by native +// Windows code. +type GUID windows.GUID diff --git a/vendor/github.com/Microsoft/go-winio/pkg/security/grantvmgroupaccess.go b/vendor/github.com/Microsoft/go-winio/pkg/security/grantvmgroupaccess.go index fca241590..602920786 100644 --- a/vendor/github.com/Microsoft/go-winio/pkg/security/grantvmgroupaccess.go +++ b/vendor/github.com/Microsoft/go-winio/pkg/security/grantvmgroupaccess.go @@ -3,11 +3,10 @@ package security import ( + "fmt" "os" "syscall" "unsafe" - - "github.com/pkg/errors" ) type ( @@ -72,7 +71,7 @@ func GrantVmGroupAccess(name string) error { // Stat (to determine if `name` is a directory). s, err := os.Stat(name) if err != nil { - return errors.Wrapf(err, "%s os.Stat %s", gvmga, name) + return fmt.Errorf("%s os.Stat %s: %w", gvmga, name, err) } // Get a handle to the file/directory. Must defer Close on success. @@ -88,7 +87,7 @@ func GrantVmGroupAccess(name string) error { sd := uintptr(0) origDACL := uintptr(0) if err := getSecurityInfo(fd, uint32(ot), uint32(si), nil, nil, &origDACL, nil, &sd); err != nil { - return errors.Wrapf(err, "%s GetSecurityInfo %s", gvmga, name) + return fmt.Errorf("%s GetSecurityInfo %s: %w", gvmga, name, err) } defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(sd))) @@ -102,7 +101,7 @@ func GrantVmGroupAccess(name string) error { // And finally use SetSecurityInfo to apply the updated DACL. if err := setSecurityInfo(fd, uint32(ot), uint32(si), uintptr(0), uintptr(0), newDACL, uintptr(0)); err != nil { - return errors.Wrapf(err, "%s SetSecurityInfo %s", gvmga, name) + return fmt.Errorf("%s SetSecurityInfo %s: %w", gvmga, name, err) } return nil @@ -120,7 +119,7 @@ func createFile(name string, isDir bool) (syscall.Handle, error) { } fd, err := syscall.CreateFile(&namep[0], da, sm, nil, syscall.OPEN_EXISTING, fa, 0) if err != nil { - return 0, errors.Wrapf(err, "%s syscall.CreateFile %s", gvmga, name) + return 0, fmt.Errorf("%s syscall.CreateFile %s: %w", gvmga, name, err) } return fd, nil } @@ -131,7 +130,7 @@ func generateDACLWithAcesAdded(name string, isDir bool, origDACL uintptr) (uintp // Generate pointers to the SIDs based on the string SIDs sid, err := syscall.StringToSid(sidVmGroup) if err != nil { - return 0, errors.Wrapf(err, "%s syscall.StringToSid %s %s", gvmga, name, sidVmGroup) + return 0, fmt.Errorf("%s syscall.StringToSid %s %s: %w", gvmga, name, sidVmGroup, err) } inheritance := inheritModeNoInheritance @@ -154,7 +153,7 @@ func generateDACLWithAcesAdded(name string, isDir bool, origDACL uintptr) (uintp modifiedDACL := uintptr(0) if err := setEntriesInAcl(uintptr(uint32(1)), uintptr(unsafe.Pointer(&eaArray[0])), origDACL, &modifiedDACL); err != nil { - return 0, errors.Wrapf(err, "%s SetEntriesInAcl %s", gvmga, name) + return 0, fmt.Errorf("%s SetEntriesInAcl %s: %w", gvmga, name, err) } return modifiedDACL, nil diff --git a/vendor/github.com/Microsoft/go-winio/vhd/vhd.go b/vendor/github.com/Microsoft/go-winio/vhd/vhd.go index a33a36c0f..f7f78fc23 100644 --- a/vendor/github.com/Microsoft/go-winio/vhd/vhd.go +++ b/vendor/github.com/Microsoft/go-winio/vhd/vhd.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package vhd @@ -7,14 +8,13 @@ import ( "syscall" "github.com/Microsoft/go-winio/pkg/guid" - "github.com/pkg/errors" "golang.org/x/sys/windows" ) //go:generate go run mksyscall_windows.go -output zvhd_windows.go vhd.go //sys createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (win32err error) = virtdisk.CreateVirtualDisk -//sys openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (win32err error) = virtdisk.OpenVirtualDisk +//sys openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (win32err error) = virtdisk.OpenVirtualDisk //sys attachVirtualDisk(handle syscall.Handle, securityDescriptor *uintptr, attachVirtualDiskFlag uint32, providerSpecificFlags uint32, parameters *AttachVirtualDiskParameters, overlapped *syscall.Overlapped) (win32err error) = virtdisk.AttachVirtualDisk //sys detachVirtualDisk(handle syscall.Handle, detachVirtualDiskFlags uint32, providerSpecificFlags uint32) (win32err error) = virtdisk.DetachVirtualDisk //sys getVirtualDiskPhysicalPath(handle syscall.Handle, diskPathSizeInBytes *uint32, buffer *uint16) (win32err error) = virtdisk.GetVirtualDiskPhysicalPath @@ -62,13 +62,27 @@ type OpenVirtualDiskParameters struct { Version2 OpenVersion2 } +// The higher level `OpenVersion2` struct uses bools to refer to `GetInfoOnly` and `ReadOnly` for ease of use. However, +// the internal windows structure uses `BOOLS` aka int32s for these types. `openVersion2` is used for translating +// `OpenVersion2` fields to the correct windows internal field types on the `Open____` methods. +type openVersion2 struct { + getInfoOnly int32 + readOnly int32 + resiliencyGUID guid.GUID +} + +type openVirtualDiskParameters struct { + version uint32 + version2 openVersion2 +} + type AttachVersion2 struct { RestrictedOffset uint64 RestrictedLength uint64 } type AttachVirtualDiskParameters struct { - Version uint32 // Must always be set to 2 + Version uint32 Version2 AttachVersion2 } @@ -146,16 +160,13 @@ func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error { return err } - if err := syscall.CloseHandle(handle); err != nil { - return err - } - return nil + return syscall.CloseHandle(handle) } // DetachVirtualDisk detaches a virtual hard disk by handle. func DetachVirtualDisk(handle syscall.Handle) (err error) { if err := detachVirtualDisk(handle, 0, 0); err != nil { - return errors.Wrap(err, "failed to detach virtual disk") + return fmt.Errorf("failed to detach virtual disk: %w", err) } return nil } @@ -185,7 +196,7 @@ func AttachVirtualDisk(handle syscall.Handle, attachVirtualDiskFlag AttachVirtua parameters, nil, ); err != nil { - return errors.Wrap(err, "failed to attach virtual disk") + return fmt.Errorf("failed to attach virtual disk: %w", err) } return nil } @@ -209,7 +220,7 @@ func AttachVhd(path string) (err error) { AttachVirtualDiskFlagNone, ¶ms, ); err != nil { - return errors.Wrap(err, "failed to attach virtual disk") + return fmt.Errorf("failed to attach virtual disk: %w", err) } return nil } @@ -234,19 +245,35 @@ func OpenVirtualDiskWithParameters(vhdPath string, virtualDiskAccessMask Virtual var ( handle syscall.Handle defaultType VirtualStorageType + getInfoOnly int32 + readOnly int32 ) if parameters.Version != 2 { return handle, fmt.Errorf("only version 2 VHDs are supported, found version: %d", parameters.Version) } + if parameters.Version2.GetInfoOnly { + getInfoOnly = 1 + } + if parameters.Version2.ReadOnly { + readOnly = 1 + } + params := &openVirtualDiskParameters{ + version: parameters.Version, + version2: openVersion2{ + getInfoOnly, + readOnly, + parameters.Version2.ResiliencyGUID, + }, + } if err := openVirtualDisk( &defaultType, vhdPath, uint32(virtualDiskAccessMask), uint32(openVirtualDiskFlags), - parameters, + params, &handle, ); err != nil { - return 0, errors.Wrap(err, "failed to open virtual disk") + return 0, fmt.Errorf("failed to open virtual disk: %w", err) } return handle, nil } @@ -272,7 +299,7 @@ func CreateVirtualDisk(path string, virtualDiskAccessMask VirtualDiskAccessMask, nil, &handle, ); err != nil { - return handle, errors.Wrap(err, "failed to create virtual disk") + return handle, fmt.Errorf("failed to create virtual disk: %w", err) } return handle, nil } @@ -290,7 +317,7 @@ func GetVirtualDiskPhysicalPath(handle syscall.Handle) (_ string, err error) { &diskPathSizeInBytes, &diskPhysicalPathBuf[0], ); err != nil { - return "", errors.Wrap(err, "failed to get disk physical path") + return "", fmt.Errorf("failed to get disk physical path: %w", err) } return windows.UTF16ToString(diskPhysicalPathBuf[:]), nil } @@ -314,10 +341,10 @@ func CreateDiffVhd(diffVhdPath, baseVhdPath string, blockSizeInMB uint32) error createParams, ) if err != nil { - return fmt.Errorf("failed to create differencing vhd: %s", err) + return fmt.Errorf("failed to create differencing vhd: %w", err) } if err := syscall.CloseHandle(vhdHandle); err != nil { - return fmt.Errorf("failed to close differencing vhd handle: %s", err) + return fmt.Errorf("failed to close differencing vhd handle: %w", err) } return nil } diff --git a/vendor/github.com/Microsoft/go-winio/vhd/zvhd_windows.go b/vendor/github.com/Microsoft/go-winio/vhd/zvhd_windows.go index 7fb5f3651..1d7498db3 100644 --- a/vendor/github.com/Microsoft/go-winio/vhd/zvhd_windows.go +++ b/vendor/github.com/Microsoft/go-winio/vhd/zvhd_windows.go @@ -88,7 +88,7 @@ func getVirtualDiskPhysicalPath(handle syscall.Handle, diskPathSizeInBytes *uint return } -func openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (win32err error) { +func openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (win32err error) { var _p0 *uint16 _p0, win32err = syscall.UTF16PtrFromString(path) if win32err != nil { @@ -97,7 +97,7 @@ func openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtua return _openVirtualDisk(virtualStorageType, _p0, virtualDiskAccessMask, openVirtualDiskFlags, parameters, handle) } -func _openVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (win32err error) { +func _openVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (win32err error) { r0, _, _ := syscall.Syscall6(procOpenVirtualDisk.Addr(), 6, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(openVirtualDiskFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(handle))) if r0 != 0 { win32err = syscall.Errno(r0) diff --git a/vendor/github.com/antlr/antlr4/LICENSE.txt b/vendor/github.com/antlr/antlr4/LICENSE.txt deleted file mode 100644 index 2042d1bda..000000000 --- a/vendor/github.com/antlr/antlr4/LICENSE.txt +++ /dev/null @@ -1,52 +0,0 @@ -[The "BSD 3-clause license"] -Copyright (c) 2012-2017 The ANTLR Project. 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 AUTHOR ``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 AUTHOR 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. - -===== - -MIT License for codepointat.js from https://git.io/codepointat -MIT License for fromcodepoint.js from https://git.io/vDW1m - -Copyright Mathias Bynens - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/LICENSE b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/LICENSE new file mode 100644 index 000000000..52cf18e42 --- /dev/null +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/LICENSE @@ -0,0 +1,26 @@ +Copyright 2021 The ANTLR Project + +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. diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config.go index 0535d5246..97ba417f7 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config.go @@ -251,7 +251,7 @@ func (l *LexerATNConfig) hash() int { f = 0 } h := murmurInit(7) - h = murmurUpdate(h, l.state.hash()) + h = murmurUpdate(h, l.state.GetStateNumber()) h = murmurUpdate(h, l.alt) h = murmurUpdate(h, l.context.hash()) h = murmurUpdate(h, l.semanticContext.hash()) diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config_set.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config_set.go index d9f74755f..51d6ab82a 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config_set.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config_set.go @@ -11,7 +11,7 @@ type ATNConfigSet interface { Add(ATNConfig, *DoubleDict) bool AddAll([]ATNConfig) bool - GetStates() *Set + GetStates() Set GetPredicates() []SemanticContext GetItems() []ATNConfig @@ -35,6 +35,8 @@ type ATNConfigSet interface { GetConflictingAlts() *BitSet SetConflictingAlts(*BitSet) + Alts() *BitSet + FullContext() bool GetUniqueAlt() int @@ -55,7 +57,7 @@ type BaseATNConfigSet struct { // effectively doubles the number of objects associated with ATNConfigs. All // keys are hashed by (s, i, _, pi), not including the context. Wiped out when // read-only because a set becomes a DFA state. - configLookup *Set + configLookup Set // configs is the added elements. configs []ATNConfig @@ -91,11 +93,19 @@ type BaseATNConfigSet struct { uniqueAlt int } +func (b *BaseATNConfigSet) Alts() *BitSet { + alts := NewBitSet() + for _, it := range b.configs { + alts.add(it.GetAlt()) + } + return alts +} + func NewBaseATNConfigSet(fullCtx bool) *BaseATNConfigSet { return &BaseATNConfigSet{ - cachedHash: -1, - configLookup: NewSet(nil, equalATNConfigs), - fullCtx: fullCtx, + cachedHash: -1, + configLookup: NewArray2DHashSetWithCap(hashATNConfig, equalATNConfigs, 16, 2), + fullCtx: fullCtx, } } @@ -116,12 +126,11 @@ func (b *BaseATNConfigSet) Add(config ATNConfig, mergeCache *DoubleDict) bool { b.dipsIntoOuterContext = true } - existing := b.configLookup.add(config).(ATNConfig) + existing := b.configLookup.Add(config).(ATNConfig) if existing == config { b.cachedHash = -1 b.configs = append(b.configs, config) // Track order here - return true } @@ -145,11 +154,11 @@ func (b *BaseATNConfigSet) Add(config ATNConfig, mergeCache *DoubleDict) bool { return true } -func (b *BaseATNConfigSet) GetStates() *Set { - states := NewSet(nil, nil) +func (b *BaseATNConfigSet) GetStates() Set { + states := NewArray2DHashSet(nil, nil) for i := 0; i < len(b.configs); i++ { - states.add(b.configs[i].GetState()) + states.Add(b.configs[i].GetState()) } return states @@ -186,7 +195,7 @@ func (b *BaseATNConfigSet) OptimizeConfigs(interpreter *BaseATNSimulator) { panic("set is read-only") } - if b.configLookup.length() == 0 { + if b.configLookup.Len() == 0 { return } @@ -236,13 +245,11 @@ func (b *BaseATNConfigSet) hash() int { } func (b *BaseATNConfigSet) hashCodeConfigs() int { - h := murmurInit(1) - for _, c := range b.configs { - if c != nil { - h = murmurUpdate(h, c.hash()) - } + h := 1 + for _, config := range b.configs { + h = 31*h + config.hash() } - return murmurFinish(h, len(b.configs)) + return h } func (b *BaseATNConfigSet) Length() int { @@ -258,7 +265,7 @@ func (b *BaseATNConfigSet) Contains(item ATNConfig) bool { panic("not implemented for read-only sets") } - return b.configLookup.contains(item) + return b.configLookup.Contains(item) } func (b *BaseATNConfigSet) ContainsFast(item ATNConfig) bool { @@ -266,7 +273,7 @@ func (b *BaseATNConfigSet) ContainsFast(item ATNConfig) bool { panic("not implemented for read-only sets") } - return b.configLookup.contains(item) // TODO: containsFast is not implemented for Set + return b.configLookup.Contains(item) // TODO: containsFast is not implemented for Set } func (b *BaseATNConfigSet) Clear() { @@ -276,7 +283,7 @@ func (b *BaseATNConfigSet) Clear() { b.configs = make([]ATNConfig, 0) b.cachedHash = -1 - b.configLookup = NewSet(nil, equalATNConfigs) + b.configLookup = NewArray2DHashSet(nil, equalATNConfigs) } func (b *BaseATNConfigSet) FullContext() bool { @@ -358,11 +365,20 @@ type OrderedATNConfigSet struct { func NewOrderedATNConfigSet() *OrderedATNConfigSet { b := NewBaseATNConfigSet(false) - b.configLookup = NewSet(nil, nil) + b.configLookup = NewArray2DHashSet(nil, nil) return &OrderedATNConfigSet{BaseATNConfigSet: b} } +func hashATNConfig(i interface{}) int { + o := i.(ATNConfig) + hash := 7 + hash = 31*hash + o.GetState().GetStateNumber() + hash = 31*hash + o.GetAlt() + hash = 31*hash + o.GetSemanticContext().hash() + return hash +} + func equalATNConfigs(a, b interface{}) bool { if a == nil || b == nil { return false @@ -379,9 +395,13 @@ func equalATNConfigs(a, b interface{}) bool { return false } - nums := ai.GetState().GetStateNumber() == bi.GetState().GetStateNumber() - alts := ai.GetAlt() == bi.GetAlt() - cons := ai.GetSemanticContext().equals(bi.GetSemanticContext()) + if ai.GetState().GetStateNumber() != bi.GetState().GetStateNumber() { + return false + } - return nums && alts && cons + if ai.GetAlt() != bi.GetAlt() { + return false + } + + return ai.GetSemanticContext().equals(bi.GetSemanticContext()) } diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa.go index d6079aa20..770c32a6b 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa.go @@ -26,6 +26,7 @@ type DFA struct { // precedenceDfa is the backing field for isPrecedenceDfa and setPrecedenceDfa. // True if the DFA is for a precedence decision and false otherwise. precedenceDfa bool + precedenceDfaMu sync.RWMutex } func NewDFA(atnStartState DecisionState, decision int) *DFA { @@ -41,25 +42,22 @@ func NewDFA(atnStartState DecisionState, decision int) *DFA { // state exists for the specified precedence and nil otherwise. d must be a // precedence DFA. See also isPrecedenceDfa. func (d *DFA) getPrecedenceStartState(precedence int) *DFAState { - if !d.precedenceDfa { + if !d.getPrecedenceDfa() { panic("only precedence DFAs may contain a precedence start state") } - d.s0Mu.RLock() - defer d.s0Mu.RUnlock() - // s0.edges is never nil for a precedence DFA - if precedence < 0 || precedence >= len(d.s0.edges) { + if precedence < 0 || precedence >= len(d.getS0().getEdges()) { return nil } - return d.s0.edges[precedence] + return d.getS0().getIthEdge(precedence) } // setPrecedenceStartState sets the start state for the current precedence. d // must be a precedence DFA. See also isPrecedenceDfa. func (d *DFA) setPrecedenceStartState(precedence int, startState *DFAState) { - if !d.precedenceDfa { + if !d.getPrecedenceDfa() { panic("only precedence DFAs may contain a precedence start state") } @@ -67,17 +65,23 @@ func (d *DFA) setPrecedenceStartState(precedence int, startState *DFAState) { return } - d.s0Mu.Lock() - defer d.s0Mu.Unlock() - // Synchronization on s0 here is ok. When the DFA is turned into a // precedence DFA, s0 will be initialized once and not updated again. s0.edges // is never nil for a precedence DFA. - if precedence >= len(d.s0.edges) { - d.s0.edges = append(d.s0.edges, make([]*DFAState, precedence+1-len(d.s0.edges))...) + s0 := d.getS0() + if precedence >= s0.numEdges() { + edges := append(s0.getEdges(), make([]*DFAState, precedence+1-s0.numEdges())...) + s0.setEdges(edges) + d.setS0(s0) } - d.s0.edges[precedence] = startState + s0.setIthEdge(precedence, startState) +} + +func (d *DFA) getPrecedenceDfa() bool { + d.precedenceDfaMu.RLock() + defer d.precedenceDfaMu.RUnlock() + return d.precedenceDfa } // setPrecedenceDfa sets whether d is a precedence DFA. If precedenceDfa differs @@ -86,20 +90,22 @@ func (d *DFA) setPrecedenceStartState(precedence int, startState *DFAState) { // store the start states for individual precedence values if precedenceDfa is // true or nil otherwise, and d.precedenceDfa is updated. func (d *DFA) setPrecedenceDfa(precedenceDfa bool) { - if d.precedenceDfa != precedenceDfa { - d.states = make(map[int]*DFAState) + if d.getPrecedenceDfa() != precedenceDfa { + d.setStates(make(map[int]*DFAState)) if precedenceDfa { precedenceState := NewDFAState(-1, NewBaseATNConfigSet(false)) - precedenceState.edges = make([]*DFAState, 0) + precedenceState.setEdges(make([]*DFAState, 0)) precedenceState.isAcceptState = false precedenceState.requiresFullContext = false - d.s0 = precedenceState + d.setS0(precedenceState) } else { - d.s0 = nil + d.setS0(nil) } + d.precedenceDfaMu.Lock() + defer d.precedenceDfaMu.Unlock() d.precedenceDfa = precedenceDfa } } @@ -123,6 +129,12 @@ func (d *DFA) getState(hash int) (*DFAState, bool) { return s, ok } +func (d *DFA) setStates(states map[int]*DFAState) { + d.statesMu.Lock() + defer d.statesMu.Unlock() + d.states = states +} + func (d *DFA) setState(hash int, state *DFAState) { d.statesMu.Lock() defer d.statesMu.Unlock() @@ -155,7 +167,7 @@ func (d *DFA) sortedStates() []*DFAState { } func (d *DFA) String(literalNames []string, symbolicNames []string) string { - if d.s0 == nil { + if d.getS0() == nil { return "" } @@ -163,7 +175,7 @@ func (d *DFA) String(literalNames []string, symbolicNames []string) string { } func (d *DFA) ToLexerString() string { - if d.s0 == nil { + if d.getS0() == nil { return "" } diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_serializer.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_serializer.go index 4c0f69022..bf2ccc06c 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_serializer.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_serializer.go @@ -7,6 +7,7 @@ package antlr import ( "fmt" "strconv" + "strings" ) // DFASerializer is a DFA walker that knows how to dump them to serialized @@ -34,7 +35,7 @@ func NewDFASerializer(dfa *DFA, literalNames, symbolicNames []string) *DFASerial } func (d *DFASerializer) String() string { - if d.dfa.s0 == nil { + if d.dfa.getS0() == nil { return "" } @@ -112,11 +113,16 @@ func NewLexerDFASerializer(dfa *DFA) *LexerDFASerializer { } func (l *LexerDFASerializer) getEdgeLabel(i int) string { - return "'" + string(i) + "'" + var sb strings.Builder + sb.Grow(6) + sb.WriteByte('\'') + sb.WriteRune(rune(i)) + sb.WriteByte('\'') + return sb.String() } func (l *LexerDFASerializer) String() string { - if l.dfa.s0 == nil { + if l.dfa.getS0() == nil { return "" } diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_state.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_state.go index 38e918ad9..3a81706ad 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_state.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_state.go @@ -6,6 +6,7 @@ package antlr import ( "fmt" + "sync" ) // PredPrediction maps a predicate to a predicted alternative. @@ -49,7 +50,8 @@ type DFAState struct { // edges elements point to the target of the symbol. Shift up by 1 so (-1) // Token.EOF maps to the first element. - edges []*DFAState + edges []*DFAState + edgesMu sync.RWMutex isAcceptState bool @@ -90,22 +92,52 @@ func NewDFAState(stateNumber int, configs ATNConfigSet) *DFAState { } // GetAltSet gets the set of all alts mentioned by all ATN configurations in d. -func (d *DFAState) GetAltSet() *Set { - alts := NewSet(nil, nil) +func (d *DFAState) GetAltSet() Set { + alts := NewArray2DHashSet(nil, nil) if d.configs != nil { for _, c := range d.configs.GetItems() { - alts.add(c.GetAlt()) + alts.Add(c.GetAlt()) } } - if alts.length() == 0 { + if alts.Len() == 0 { return nil } return alts } +func (d *DFAState) getEdges() []*DFAState { + d.edgesMu.RLock() + defer d.edgesMu.RUnlock() + return d.edges +} + +func (d *DFAState) numEdges() int { + d.edgesMu.RLock() + defer d.edgesMu.RUnlock() + return len(d.edges) +} + +func (d *DFAState) getIthEdge(i int) *DFAState { + d.edgesMu.RLock() + defer d.edgesMu.RUnlock() + return d.edges[i] +} + +func (d *DFAState) setEdges(newEdges []*DFAState) { + d.edgesMu.Lock() + defer d.edgesMu.Unlock() + d.edges = newEdges +} + +func (d *DFAState) setIthEdge(i int, edge *DFAState) { + d.edgesMu.Lock() + defer d.edgesMu.Unlock() + d.edges[i] = edge +} + func (d *DFAState) setPrediction(v int) { d.prediction = v } @@ -141,26 +173,11 @@ func (d *DFAState) String() string { } } - return fmt.Sprintf("%d:%s%s", fmt.Sprint(d.configs), s) + return fmt.Sprintf("%d:%s%s", d.stateNumber, fmt.Sprint(d.configs), s) } func (d *DFAState) hash() int { - h := murmurInit(11) - - c := 1 - if d.isAcceptState { - if d.predicates != nil { - for _, p := range d.predicates { - h = murmurUpdate(h, p.alt) - h = murmurUpdate(h, p.pred.hash()) - c += 2 - } - } else { - h = murmurUpdate(h, d.prediction) - c += 1 - } - } - + h := murmurInit(7) h = murmurUpdate(h, d.configs.hash()) - return murmurFinish(h, c) -} \ No newline at end of file + return murmurFinish(h, 1) +} diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/go.mod b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/go.mod new file mode 100644 index 000000000..004cf3465 --- /dev/null +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/go.mod @@ -0,0 +1,3 @@ +module github.com/antlr/antlr4/runtime/Go/antlr + +go 1.16 diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/interval_set.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/interval_set.go index 510d90911..1e9393adb 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/interval_set.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/interval_set.go @@ -226,16 +226,28 @@ func (i *IntervalSet) StringVerbose(literalNames []string, symbolicNames []strin func (i *IntervalSet) toCharString() string { names := make([]string, len(i.intervals)) + var sb strings.Builder + for j := 0; j < len(i.intervals); j++ { v := i.intervals[j] if v.Stop == v.Start+1 { if v.Start == TokenEOF { names = append(names, "") } else { - names = append(names, ("'" + string(v.Start) + "'")) + sb.WriteByte('\'') + sb.WriteRune(rune(v.Start)) + sb.WriteByte('\'') + names = append(names, sb.String()) + sb.Reset() } } else { - names = append(names, "'"+string(v.Start)+"'..'"+string(v.Stop-1)+"'") + sb.WriteByte('\'') + sb.WriteRune(rune(v.Start)) + sb.WriteString("'..'") + sb.WriteRune(rune(v.Stop - 1)) + sb.WriteByte('\'') + names = append(names, sb.String()) + sb.Reset() } } if len(names) > 1 { diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action.go index 20df84f94..5a325be13 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action.go @@ -414,10 +414,9 @@ func (l *LexerIndexedCustomAction) execute(lexer Lexer) { func (l *LexerIndexedCustomAction) hash() int { h := murmurInit(0) - h = murmurUpdate(h, l.actionType) h = murmurUpdate(h, l.offset) h = murmurUpdate(h, l.lexerAction.hash()) - return murmurFinish(h, 3) + return murmurFinish(h, 2) } func (l *LexerIndexedCustomAction) equals(other LexerAction) bool { diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action_executor.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action_executor.go index 80b949a1a..056941dd6 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action_executor.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action_executor.go @@ -161,10 +161,13 @@ func (l *LexerActionExecutor) hash() int { func (l *LexerActionExecutor) equals(other interface{}) bool { if l == other { return true - } else if _, ok := other.(*LexerActionExecutor); !ok { - return false - } else { - return l.cachedHash == other.(*LexerActionExecutor).cachedHash && - &l.lexerActions == &other.(*LexerActionExecutor).lexerActions } + othert, ok := other.(*LexerActionExecutor) + if !ok { + return false + } + if othert == nil { + return false + } + return l.cachedHash == othert.cachedHash && &l.lexerActions == &othert.lexerActions } diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_atn_simulator.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_atn_simulator.go index 131364f75..730bea47a 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_atn_simulator.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_atn_simulator.go @@ -7,6 +7,7 @@ package antlr import ( "fmt" "strconv" + "strings" ) var ( @@ -90,11 +91,11 @@ func (l *LexerATNSimulator) Match(input CharStream, mode int) int { dfa := l.decisionToDFA[mode] - if dfa.s0 == nil { + if dfa.getS0() == nil { return l.MatchATN(input) } - return l.execATN(input, dfa.s0) + return l.execATN(input, dfa.getS0()) } func (l *LexerATNSimulator) reset() { @@ -202,11 +203,11 @@ func (l *LexerATNSimulator) execATN(input CharStream, ds0 *DFAState) int { // {@code t}, or {@code nil} if the target state for l edge is not // already cached func (l *LexerATNSimulator) getExistingTargetState(s *DFAState, t int) *DFAState { - if s.edges == nil || t < LexerATNSimulatorMinDFAEdge || t > LexerATNSimulatorMaxDFAEdge { + if s.getEdges() == nil || t < LexerATNSimulatorMinDFAEdge || t > LexerATNSimulatorMaxDFAEdge { return nil } - target := s.edges[t-LexerATNSimulatorMinDFAEdge] + target := s.getIthEdge(t - LexerATNSimulatorMinDFAEdge) if LexerATNSimulatorDebug && target != nil { fmt.Println("reuse state " + strconv.Itoa(s.stateNumber) + " edge to " + strconv.Itoa(target.stateNumber)) } @@ -299,7 +300,7 @@ func (l *LexerATNSimulator) getReachableConfigSet(input CharStream, closure ATNC func (l *LexerATNSimulator) accept(input CharStream, lexerActionExecutor *LexerActionExecutor, startIndex, index, line, charPos int) { if LexerATNSimulatorDebug { - fmt.Printf("ACTION %s\n", lexerActionExecutor) + fmt.Printf("ACTION %v\n", lexerActionExecutor) } // seek to after last char in token input.Seek(index) @@ -550,11 +551,11 @@ func (l *LexerATNSimulator) addDFAEdge(from *DFAState, tk int, to *DFAState, cfg if LexerATNSimulatorDebug { fmt.Println("EDGE " + from.String() + " -> " + to.String() + " upon " + strconv.Itoa(tk)) } - if from.edges == nil { + if from.getEdges() == nil { // make room for tokens 1..n and -1 masquerading as index 0 - from.edges = make([]*DFAState, LexerATNSimulatorMaxDFAEdge-LexerATNSimulatorMinDFAEdge+1) + from.setEdges(make([]*DFAState, LexerATNSimulatorMaxDFAEdge-LexerATNSimulatorMinDFAEdge+1)) } - from.edges[tk-LexerATNSimulatorMinDFAEdge] = to // connect + from.setIthEdge(tk-LexerATNSimulatorMinDFAEdge, to) // connect return to } @@ -630,7 +631,13 @@ func (l *LexerATNSimulator) GetTokenName(tt int) string { return "EOF" } - return "'" + string(tt) + "'" + var sb strings.Builder + sb.Grow(6) + sb.WriteByte('\'') + sb.WriteRune(rune(tt)) + sb.WriteByte('\'') + + return sb.String() } func resetSimState(sim *SimState) { diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/ll1_analyzer.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/ll1_analyzer.go index f5afd09b3..ebd43e456 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/ll1_analyzer.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/ll1_analyzer.go @@ -38,7 +38,7 @@ func (la *LL1Analyzer) getDecisionLookahead(s ATNState) []*IntervalSet { look := make([]*IntervalSet, count) for alt := 0; alt < count; alt++ { look[alt] = NewIntervalSet() - lookBusy := NewSet(nil, nil) + lookBusy := NewArray2DHashSet(nil, nil) seeThruPreds := false // fail to get lookahead upon pred la.look1(s.GetTransitions()[alt].getTarget(), nil, BasePredictionContextEMPTY, look[alt], lookBusy, NewBitSet(), seeThruPreds, false) // Wipe out lookahead for la alternative if we found nothing @@ -75,7 +75,7 @@ func (la *LL1Analyzer) Look(s, stopState ATNState, ctx RuleContext) *IntervalSet if ctx != nil { lookContext = predictionContextFromRuleContext(s.GetATN(), ctx) } - la.look1(s, stopState, lookContext, r, NewSet(nil, nil), NewBitSet(), seeThruPreds, true) + la.look1(s, stopState, lookContext, r, NewArray2DHashSet(nil, nil), NewBitSet(), seeThruPreds, true) return r } @@ -109,32 +109,22 @@ func (la *LL1Analyzer) Look(s, stopState ATNState, ctx RuleContext) *IntervalSet // outermost context is reached. This parameter has no effect if {@code ctx} // is {@code nil}. -func (la *LL1Analyzer) look2(s, stopState ATNState, ctx PredictionContext, look *IntervalSet, lookBusy *Set, calledRuleStack *BitSet, seeThruPreds, addEOF bool, i int) { +func (la *LL1Analyzer) look2(s, stopState ATNState, ctx PredictionContext, look *IntervalSet, lookBusy Set, calledRuleStack *BitSet, seeThruPreds, addEOF bool, i int) { returnState := la.atn.states[ctx.getReturnState(i)] - - removed := calledRuleStack.contains(returnState.GetRuleIndex()) - - defer func() { - if removed { - calledRuleStack.add(returnState.GetRuleIndex()) - } - }() - - calledRuleStack.remove(returnState.GetRuleIndex()) la.look1(returnState, stopState, ctx.GetParent(i), look, lookBusy, calledRuleStack, seeThruPreds, addEOF) } -func (la *LL1Analyzer) look1(s, stopState ATNState, ctx PredictionContext, look *IntervalSet, lookBusy *Set, calledRuleStack *BitSet, seeThruPreds, addEOF bool) { +func (la *LL1Analyzer) look1(s, stopState ATNState, ctx PredictionContext, look *IntervalSet, lookBusy Set, calledRuleStack *BitSet, seeThruPreds, addEOF bool) { c := NewBaseATNConfig6(s, 0, ctx) - if lookBusy.contains(c) { + if lookBusy.Contains(c) { return } - lookBusy.add(c) + lookBusy.Add(c) if s == stopState { if ctx == nil { @@ -158,6 +148,13 @@ func (la *LL1Analyzer) look1(s, stopState ATNState, ctx PredictionContext, look } if ctx != BasePredictionContextEMPTY { + removed := calledRuleStack.contains(s.GetRuleIndex()) + defer func() { + if removed { + calledRuleStack.add(s.GetRuleIndex()) + } + }() + calledRuleStack.remove(s.GetRuleIndex()) // run thru all possible stack tops in ctx for i := 0; i < ctx.length(); i++ { returnState := la.atn.states[ctx.getReturnState(i)] @@ -201,7 +198,7 @@ func (la *LL1Analyzer) look1(s, stopState ATNState, ctx PredictionContext, look } } -func (la *LL1Analyzer) look3(stopState ATNState, ctx PredictionContext, look *IntervalSet, lookBusy *Set, calledRuleStack *BitSet, seeThruPreds, addEOF bool, t1 *RuleTransition) { +func (la *LL1Analyzer) look3(stopState ATNState, ctx PredictionContext, look *IntervalSet, lookBusy Set, calledRuleStack *BitSet, seeThruPreds, addEOF bool, t1 *RuleTransition) { newContext := SingletonBasePredictionContextCreate(ctx, t1.followState.GetStateNumber()) diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser_atn_simulator.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser_atn_simulator.go index 128b9a96d..d7a3665be 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser_atn_simulator.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser_atn_simulator.go @@ -15,6 +15,7 @@ var ( ParserATNSimulatorListATNDecisions = false ParserATNSimulatorDFADebug = false ParserATNSimulatorRetryDebug = false + TurnOffLRLoopEntryBranchOpt = false ) type ParserATNSimulator struct { @@ -95,13 +96,13 @@ func (p *ParserATNSimulator) AdaptivePredict(input TokenStream, decision int, ou // Now we are certain to have a specific decision's DFA // But, do we still need an initial state? var s0 *DFAState - if dfa.precedenceDfa { + if dfa.getPrecedenceDfa() { // the start state for a precedence DFA depends on the current // parser precedence, and is provided by a DFA method. s0 = dfa.getPrecedenceStartState(p.parser.GetPrecedence()) } else { // the start state for a "regular" DFA is just s0 - s0 = dfa.s0 + s0 = dfa.getS0() } if s0 == nil { @@ -120,7 +121,7 @@ func (p *ParserATNSimulator) AdaptivePredict(input TokenStream, decision int, ou t2 := dfa.atnStartState t, ok := t2.(*StarLoopEntryState) - if !dfa.precedenceDfa && ok { + if !dfa.getPrecedenceDfa() && ok { if t.precedenceRuleDecision { dfa.setPrecedenceDfa(true) } @@ -128,19 +129,20 @@ func (p *ParserATNSimulator) AdaptivePredict(input TokenStream, decision int, ou fullCtx := false s0Closure := p.computeStartState(dfa.atnStartState, RuleContextEmpty, fullCtx) - if dfa.precedenceDfa { + if dfa.getPrecedenceDfa() { // If p is a precedence DFA, we use applyPrecedenceFilter // to convert the computed start state to a precedence start // state. We then use DFA.setPrecedenceStartState to set the // appropriate start state for the precedence level rather // than simply setting DFA.s0. // + dfa.s0.configs = s0Closure s0Closure = p.applyPrecedenceFilter(s0Closure) s0 = p.addDFAState(dfa, NewDFAState(-1, s0Closure)) dfa.setPrecedenceStartState(p.parser.GetPrecedence(), s0) } else { s0 = p.addDFAState(dfa, NewDFAState(-1, s0Closure)) - dfa.s0 = s0 + dfa.setS0(s0) } } alt := p.execATN(dfa, s0, input, index, outerContext) @@ -259,11 +261,13 @@ func (p *ParserATNSimulator) execATN(dfa *DFA, s0 *DFAState, input TokenStream, stopIndex := input.Index() input.Seek(startIndex) alts := p.evalSemanticContext(D.predicates, outerContext, true) - if alts.length() == 0 { + + switch alts.length() { + case 0: panic(p.noViableAlt(input, outerContext, D.configs, startIndex)) - } else if alts.length() == 1 { + case 1: return alts.minValue() - } else { + default: // Report ambiguity after predicate evaluation to make sure the correct set of ambig alts is Reported. p.ReportAmbiguity(dfa, D, startIndex, stopIndex, false, alts, D.configs) return alts.minValue() @@ -291,12 +295,12 @@ func (p *ParserATNSimulator) execATN(dfa *DFA, s0 *DFAState, input TokenStream, // already cached func (p *ParserATNSimulator) getExistingTargetState(previousD *DFAState, t int) *DFAState { - edges := previousD.edges - if edges == nil { + edges := previousD.getEdges() + if edges == nil || t+1 < 0 || t+1 >= len(edges) { return nil } - return edges[t+1] + return previousD.getIthEdge(t + 1) } // Compute a target state for an edge in the DFA, and attempt to add the @@ -422,7 +426,8 @@ func (p *ParserATNSimulator) execATNWithFullContext(dfa *DFA, D *DFAState, s0 AT if reach.GetUniqueAlt() != ATNInvalidAltNumber { predictedAlt = reach.GetUniqueAlt() break - } else if p.predictionMode != PredictionModeLLExactAmbigDetection { + } + if p.predictionMode != PredictionModeLLExactAmbigDetection { predictedAlt = PredictionModeresolvesToJustOneViableAlt(altSubSets) if predictedAlt != ATNInvalidAltNumber { break @@ -479,7 +484,7 @@ func (p *ParserATNSimulator) execATNWithFullContext(dfa *DFA, D *DFAState, s0 AT // the fact that we should predict alternative 1. We just can't say for // sure that there is an ambiguity without looking further. - p.ReportAmbiguity(dfa, D, startIndex, input.Index(), foundExactAmbig, nil, reach) + p.ReportAmbiguity(dfa, D, startIndex, input.Index(), foundExactAmbig, reach.Alts(), reach) return predictedAlt } @@ -503,7 +508,7 @@ func (p *ParserATNSimulator) computeReachSet(closure ATNConfigSet, t int, fullCt // ensure that the alternative Matching the longest overall sequence is // chosen when multiple such configurations can Match the input. - var SkippedStopStates []*BaseATNConfig + var skippedStopStates []*BaseATNConfig // First figure out where we can reach on input t for _, c := range closure.GetItems() { @@ -511,14 +516,9 @@ func (p *ParserATNSimulator) computeReachSet(closure ATNConfigSet, t int, fullCt fmt.Println("testing " + p.GetTokenName(t) + " at " + c.String()) } - _, ok := c.GetState().(*RuleStopState) - - if ok { + if _, ok := c.GetState().(*RuleStopState); ok { if fullCtx || t == TokenEOF { - if SkippedStopStates == nil { - SkippedStopStates = make([]*BaseATNConfig, 0) - } - SkippedStopStates = append(SkippedStopStates, c.(*BaseATNConfig)) + skippedStopStates = append(skippedStopStates, c.(*BaseATNConfig)) if ParserATNSimulatorDebug { fmt.Println("added " + c.String() + " to SkippedStopStates") } @@ -526,8 +526,7 @@ func (p *ParserATNSimulator) computeReachSet(closure ATNConfigSet, t int, fullCt continue } - for j := 0; j < len(c.GetState().GetTransitions()); j++ { - trans := c.GetState().GetTransitions()[j] + for _, trans := range c.GetState().GetTransitions() { target := p.getReachableTarget(trans, t) if target != nil { cfg := NewBaseATNConfig4(c, target) @@ -538,6 +537,7 @@ func (p *ParserATNSimulator) computeReachSet(closure ATNConfigSet, t int, fullCt } } } + // Now figure out where the reach operation can take us... var reach ATNConfigSet @@ -550,7 +550,7 @@ func (p *ParserATNSimulator) computeReachSet(closure ATNConfigSet, t int, fullCt // condition is not true when one or more configurations have been // withheld in SkippedStopStates, or when the current symbol is EOF. // - if SkippedStopStates == nil && t != TokenEOF { + if skippedStopStates == nil && t != TokenEOF { if len(intermediate.configs) == 1 { // Don't pursue the closure if there is just one state. // It can only have one alternative just add to result @@ -568,9 +568,10 @@ func (p *ParserATNSimulator) computeReachSet(closure ATNConfigSet, t int, fullCt // if reach == nil { reach = NewBaseATNConfigSet(fullCtx) - closureBusy := NewSet(nil, nil) + closureBusy := NewArray2DHashSet(nil, nil) treatEOFAsEpsilon := t == TokenEOF - for k := 0; k < len(intermediate.configs); k++ { + amount := len(intermediate.configs) + for k := 0; k < amount; k++ { p.closure(intermediate.configs[k], reach, closureBusy, false, fullCtx, treatEOFAsEpsilon) } } @@ -602,9 +603,9 @@ func (p *ParserATNSimulator) computeReachSet(closure ATNConfigSet, t int, fullCt // chooses an alternative Matching the longest overall sequence when // multiple alternatives are viable. // - if SkippedStopStates != nil && ((!fullCtx) || (!PredictionModehasConfigInRuleStopState(reach))) { - for l := 0; l < len(SkippedStopStates); l++ { - reach.Add(SkippedStopStates[l], p.mergeCache) + if skippedStopStates != nil && ((!fullCtx) || (!PredictionModehasConfigInRuleStopState(reach))) { + for l := 0; l < len(skippedStopStates); l++ { + reach.Add(skippedStopStates[l], p.mergeCache) } } if len(reach.GetItems()) == 0 { @@ -640,10 +641,7 @@ func (p *ParserATNSimulator) removeAllConfigsNotInRuleStopState(configs ATNConfi } result := NewBaseATNConfigSet(configs.FullContext()) for _, config := range configs.GetItems() { - - _, ok := config.GetState().(*RuleStopState) - - if ok { + if _, ok := config.GetState().(*RuleStopState); ok { result.Add(config, p.mergeCache) continue } @@ -665,7 +663,7 @@ func (p *ParserATNSimulator) computeStartState(a ATNState, ctx RuleContext, full for i := 0; i < len(a.GetTransitions()); i++ { target := a.GetTransitions()[i].getTarget() c := NewBaseATNConfig6(target, i+1, initialContext) - closureBusy := NewSet(nil, nil) + closureBusy := NewArray2DHashSet(nil, nil) p.closure(c, configs, closureBusy, true, fullCtx, false) } return configs @@ -787,7 +785,7 @@ func (p *ParserATNSimulator) getPredsForAmbigAlts(ambigAlts *BitSet, configs ATN } } nPredAlts := 0 - for i := 1; i < nalts+1; i++ { + for i := 1; i <= nalts; i++ { pred := altToPred[i] if pred == nil { altToPred[i] = SemanticContextNone @@ -972,14 +970,13 @@ func (p *ParserATNSimulator) evalSemanticContext(predPredictions []*PredPredicti return predictions } -func (p *ParserATNSimulator) closure(config ATNConfig, configs ATNConfigSet, closureBusy *Set, collectPredicates, fullCtx, treatEOFAsEpsilon bool) { +func (p *ParserATNSimulator) closure(config ATNConfig, configs ATNConfigSet, closureBusy Set, collectPredicates, fullCtx, treatEOFAsEpsilon bool) { initialDepth := 0 p.closureCheckingStopState(config, configs, closureBusy, collectPredicates, fullCtx, initialDepth, treatEOFAsEpsilon) } -func (p *ParserATNSimulator) closureCheckingStopState(config ATNConfig, configs ATNConfigSet, closureBusy *Set, collectPredicates, fullCtx bool, depth int, treatEOFAsEpsilon bool) { - +func (p *ParserATNSimulator) closureCheckingStopState(config ATNConfig, configs ATNConfigSet, closureBusy Set, collectPredicates, fullCtx bool, depth int, treatEOFAsEpsilon bool) { if ParserATNSimulatorDebug { fmt.Println("closure(" + config.String() + ")") fmt.Println("configs(" + configs.String() + ")") @@ -988,8 +985,7 @@ func (p *ParserATNSimulator) closureCheckingStopState(config ATNConfig, configs } } - _, ok := config.GetState().(*RuleStopState) - if ok { + if _, ok := config.GetState().(*RuleStopState); ok { // We hit rule end. If we have context info, use it // run thru all possible stack tops in ctx if !config.GetContext().isEmpty() { @@ -1033,7 +1029,7 @@ func (p *ParserATNSimulator) closureCheckingStopState(config ATNConfig, configs } // Do the actual work of walking epsilon edges// -func (p *ParserATNSimulator) closureWork(config ATNConfig, configs ATNConfigSet, closureBusy *Set, collectPredicates, fullCtx bool, depth int, treatEOFAsEpsilon bool) { +func (p *ParserATNSimulator) closureWork(config ATNConfig, configs ATNConfigSet, closureBusy Set, collectPredicates, fullCtx bool, depth int, treatEOFAsEpsilon bool) { state := config.GetState() // optimization if !state.GetEpsilonOnlyTransitions() { @@ -1042,46 +1038,52 @@ func (p *ParserATNSimulator) closureWork(config ATNConfig, configs ATNConfigSet, // both epsilon transitions and non-epsilon transitions. } for i := 0; i < len(state.GetTransitions()); i++ { + if i == 0 && p.canDropLoopEntryEdgeInLeftRecursiveRule(config) { + continue + } + t := state.GetTransitions()[i] _, ok := t.(*ActionTransition) continueCollecting := collectPredicates && !ok c := p.getEpsilonTarget(config, t, continueCollecting, depth == 0, fullCtx, treatEOFAsEpsilon) if ci, ok := c.(*BaseATNConfig); ok && ci != nil { - if !t.getIsEpsilon() && closureBusy.add(c) != c { - // avoid infinite recursion for EOF* and EOF+ - continue - } newDepth := depth if _, ok := config.GetState().(*RuleStopState); ok { - // target fell off end of rule mark resulting c as having dipped into outer context // We can't get here if incoming config was rule stop and we had context // track how far we dip into outer context. Might // come in handy and we avoid evaluating context dependent // preds if p is > 0. - if closureBusy.add(c) != c { - // avoid infinite recursion for right-recursive rules - continue - } - - if p.dfa != nil && p.dfa.precedenceDfa { + if p.dfa != nil && p.dfa.getPrecedenceDfa() { if t.(*EpsilonTransition).outermostPrecedenceReturn == p.dfa.atnStartState.GetRuleIndex() { c.setPrecedenceFilterSuppressed(true) } } c.SetReachesIntoOuterContext(c.GetReachesIntoOuterContext() + 1) + + if closureBusy.Add(c) != c { + // avoid infinite recursion for right-recursive rules + continue + } + configs.SetDipsIntoOuterContext(true) // TODO: can remove? only care when we add to set per middle of p method newDepth-- if ParserATNSimulatorDebug { fmt.Println("dips into outer ctx: " + c.String()) } - } else if _, ok := t.(*RuleTransition); ok { - // latch when newDepth goes negative - once we step out of the entry context we can't return - if newDepth >= 0 { - newDepth++ + } else { + if !t.getIsEpsilon() && closureBusy.Add(c) != c { + // avoid infinite recursion for EOF* and EOF+ + continue + } + if _, ok := t.(*RuleTransition); ok { + // latch when newDepth goes negative - once we step out of the entry context we can't return + if newDepth >= 0 { + newDepth++ + } } } p.closureCheckingStopState(c, configs, closureBusy, continueCollecting, fullCtx, newDepth, treatEOFAsEpsilon) @@ -1089,12 +1091,93 @@ func (p *ParserATNSimulator) closureWork(config ATNConfig, configs ATNConfigSet, } } +func (p *ParserATNSimulator) canDropLoopEntryEdgeInLeftRecursiveRule(config ATNConfig) bool { + if TurnOffLRLoopEntryBranchOpt { + return false + } + + _p := config.GetState() + + // First check to see if we are in StarLoopEntryState generated during + // left-recursion elimination. For efficiency, also check if + // the context has an empty stack case. If so, it would mean + // global FOLLOW so we can't perform optimization + if startLoop, ok := _p.(StarLoopEntryState); !ok || !startLoop.precedenceRuleDecision || config.GetContext().isEmpty() || config.GetContext().hasEmptyPath() { + return false + } + + // Require all return states to return back to the same rule + // that p is in. + numCtxs := config.GetContext().length() + for i := 0; i < numCtxs; i++ { + returnState := p.atn.states[config.GetContext().getReturnState(i)] + if returnState.GetRuleIndex() != _p.GetRuleIndex() { + return false + } + } + + decisionStartState := _p.(BlockStartState).GetTransitions()[0].getTarget().(BlockStartState) + blockEndStateNum := decisionStartState.getEndState().stateNumber + blockEndState := p.atn.states[blockEndStateNum].(*BlockEndState) + + // Verify that the top of each stack context leads to loop entry/exit + // state through epsilon edges and w/o leaving rule. + + for i := 0; i < numCtxs; i++ { // for each stack context + returnStateNumber := config.GetContext().getReturnState(i) + returnState := p.atn.states[returnStateNumber] + + // all states must have single outgoing epsilon edge + if len(returnState.GetTransitions()) != 1 || !returnState.GetTransitions()[0].getIsEpsilon() { + return false + } + + // Look for prefix op case like 'not expr', (' type ')' expr + returnStateTarget := returnState.GetTransitions()[0].getTarget() + if returnState.GetStateType() == ATNStateBlockEnd && returnStateTarget == _p { + continue + } + + // Look for 'expr op expr' or case where expr's return state is block end + // of (...)* internal block; the block end points to loop back + // which points to p but we don't need to check that + if returnState == blockEndState { + continue + } + + // Look for ternary expr ? expr : expr. The return state points at block end, + // which points at loop entry state + if returnStateTarget == blockEndState { + continue + } + + // Look for complex prefix 'between expr and expr' case where 2nd expr's + // return state points at block end state of (...)* internal block + if returnStateTarget.GetStateType() == ATNStateBlockEnd && + len(returnStateTarget.GetTransitions()) == 1 && + returnStateTarget.GetTransitions()[0].getIsEpsilon() && + returnStateTarget.GetTransitions()[0].getTarget() == _p { + continue + } + + // anything else ain't conforming + return false + } + + return true +} + func (p *ParserATNSimulator) getRuleName(index int) string { if p.parser != nil && index >= 0 { return p.parser.GetRuleNames()[index] } + var sb strings.Builder + sb.Grow(32) - return "" + sb.WriteString("') + return sb.String() } func (p *ParserATNSimulator) getEpsilonTarget(config ATNConfig, t Transition, collectPredicates, inContext, fullCtx, treatEOFAsEpsilon bool) ATNConfig { @@ -1110,25 +1193,7 @@ func (p *ParserATNSimulator) getEpsilonTarget(config ATNConfig, t Transition, co return p.actionTransition(config, t.(*ActionTransition)) case TransitionEPSILON: return NewBaseATNConfig4(config, t.getTarget()) - case TransitionATOM: - // EOF transitions act like epsilon transitions after the first EOF - // transition is traversed - if treatEOFAsEpsilon { - if t.Matches(TokenEOF, 0, 1) { - return NewBaseATNConfig4(config, t.getTarget()) - } - } - return nil - case TransitionRANGE: - // EOF transitions act like epsilon transitions after the first EOF - // transition is traversed - if treatEOFAsEpsilon { - if t.Matches(TokenEOF, 0, 1) { - return NewBaseATNConfig4(config, t.getTarget()) - } - } - return nil - case TransitionSET: + case TransitionATOM, TransitionRANGE, TransitionSET: // EOF transitions act like epsilon transitions after the first EOF // transition is traversed if treatEOFAsEpsilon { @@ -1196,7 +1261,7 @@ func (p *ParserATNSimulator) predTransition(config ATNConfig, pt *PredicateTrans } } var c *BaseATNConfig - if collectPredicates && ((pt.isCtxDependent && inContext) || !pt.isCtxDependent) { + if collectPredicates && (!pt.isCtxDependent || inContext) { if fullCtx { // In full context mode, we can evaluate predicates on-the-fly // during closure, which dramatically reduces the size of @@ -1385,10 +1450,10 @@ func (p *ParserATNSimulator) addDFAEdge(dfa *DFA, from *DFAState, t int, to *DFA if from == nil || t < -1 || t > p.atn.maxTokenType { return to } - if from.edges == nil { - from.edges = make([]*DFAState, p.atn.maxTokenType+1+1) + if from.getEdges() == nil { + from.setEdges(make([]*DFAState, p.atn.maxTokenType+1+1)) } - from.edges[t+1] = to // connect + from.setIthEdge(t+1, to) // connect if ParserATNSimulatorDebug { var names []string diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/prediction_context.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/prediction_context.go index 99acb333f..9fdfd52b2 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/prediction_context.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/prediction_context.go @@ -58,9 +58,15 @@ func calculateHash(parent PredictionContext, returnState int) int { return murmurFinish(h, 2) } +var _emptyPredictionContextHash int + +func init() { + _emptyPredictionContextHash = murmurInit(1) + _emptyPredictionContextHash = murmurFinish(_emptyPredictionContextHash, 0) +} + func calculateEmptyHash() int { - h := murmurInit(1) - return murmurFinish(h, 0) + return _emptyPredictionContextHash } // Used to cache {@link BasePredictionContext} objects. Its used for the shared @@ -113,15 +119,15 @@ type BaseSingletonPredictionContext struct { } func NewBaseSingletonPredictionContext(parent PredictionContext, returnState int) *BaseSingletonPredictionContext { + var cachedHash int + if parent != nil { + cachedHash = calculateHash(parent, returnState) + } else { + cachedHash = calculateEmptyHash() + } s := new(BaseSingletonPredictionContext) - s.BasePredictionContext = NewBasePredictionContext(37) - - if parent != nil { - s.cachedHash = calculateHash(parent, returnState) - } else { - s.cachedHash = calculateEmptyHash() - } + s.BasePredictionContext = NewBasePredictionContext(cachedHash) s.parentCtx = parent s.returnState = returnState @@ -175,15 +181,7 @@ func (b *BaseSingletonPredictionContext) equals(other PredictionContext) bool { } func (b *BaseSingletonPredictionContext) hash() int { - h := murmurInit(1) - - if b.parentCtx == nil { - return murmurFinish(h, 0) - } - - h = murmurUpdate(h, b.parentCtx.hash()) - h = murmurUpdate(h, b.returnState) - return murmurFinish(h, 2) + return b.cachedHash } func (b *BaseSingletonPredictionContext) String() string { @@ -253,13 +251,20 @@ func NewArrayPredictionContext(parents []PredictionContext, returnStates []int) // from {@link //EMPTY} and non-empty. We merge {@link //EMPTY} by using // nil parent and // returnState == {@link //EmptyReturnState}. + hash := murmurInit(1) + + for _, parent := range parents { + hash = murmurUpdate(hash, parent.hash()) + } + + for _, returnState := range returnStates { + hash = murmurUpdate(hash, returnState) + } + + hash = murmurFinish(hash, len(parents)<<1) c := new(ArrayPredictionContext) - c.BasePredictionContext = NewBasePredictionContext(37) - - for i := range parents { - c.cachedHash += calculateHash(parents[i], returnStates[i]) - } + c.BasePredictionContext = NewBasePredictionContext(hash) c.parents = parents c.returnStates = returnStates @@ -305,17 +310,7 @@ func (a *ArrayPredictionContext) equals(other PredictionContext) bool { } func (a *ArrayPredictionContext) hash() int { - h := murmurInit(1) - - for _, p := range a.parents { - h = murmurUpdate(h, p.hash()) - } - - for _, r := range a.returnStates { - h = murmurUpdate(h, r) - } - - return murmurFinish(h, 2 * len(a.parents)) + return a.BasePredictionContext.cachedHash } func (a *ArrayPredictionContext) String() string { diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/recognizer.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/recognizer.go index d114800f4..12578cfb3 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/recognizer.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/recognizer.go @@ -49,7 +49,7 @@ var tokenTypeMapCache = make(map[string]int) var ruleIndexMapCache = make(map[string]int) func (b *BaseRecognizer) checkVersion(toolVersion string) { - runtimeVersion := "4.8" + runtimeVersion := "4.9.3" if runtimeVersion != toolVersion { fmt.Println("ANTLR runtime and generated code versions disagree: " + runtimeVersion + "!=" + toolVersion) } diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/semantic_context.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/semantic_context.go index 49205a162..bdbaabdc2 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/semantic_context.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/semantic_context.go @@ -108,7 +108,15 @@ func (p *Predicate) equals(other interface{}) bool { } func (p *Predicate) hash() int { - return p.ruleIndex*43 + p.predIndex*47 + h := murmurInit(0) + h = murmurUpdate(h, p.ruleIndex) + h = murmurUpdate(h, p.predIndex) + if p.isCtxDependent { + h = murmurUpdate(h, 1) + } else { + h = murmurUpdate(h, 0) + } + return murmurFinish(h, 3) } func (p *Predicate) String() string { @@ -154,21 +162,24 @@ func (p *PrecedencePredicate) equals(other interface{}) bool { } func (p *PrecedencePredicate) hash() int { - return p.precedence * 51 + h := uint32(1) + h = 31*h + uint32(p.precedence) + return int(h) } func (p *PrecedencePredicate) String() string { return "{" + strconv.Itoa(p.precedence) + ">=prec}?" } -func PrecedencePredicatefilterPrecedencePredicates(set *Set) []*PrecedencePredicate { +func PrecedencePredicatefilterPrecedencePredicates(set Set) []*PrecedencePredicate { result := make([]*PrecedencePredicate, 0) - for _, v := range set.values() { + set.Each(func(v interface{}) bool { if c2, ok := v.(*PrecedencePredicate); ok { result = append(result, c2) } - } + return true + }) return result } @@ -182,21 +193,21 @@ type AND struct { func NewAND(a, b SemanticContext) *AND { - operands := NewSet(nil, nil) + operands := NewArray2DHashSet(nil, nil) if aa, ok := a.(*AND); ok { for _, o := range aa.opnds { - operands.add(o) + operands.Add(o) } } else { - operands.add(a) + operands.Add(a) } if ba, ok := b.(*AND); ok { for _, o := range ba.opnds { - operands.add(o) + operands.Add(o) } } else { - operands.add(b) + operands.Add(b) } precedencePredicates := PrecedencePredicatefilterPrecedencePredicates(operands) if len(precedencePredicates) > 0 { @@ -209,10 +220,10 @@ func NewAND(a, b SemanticContext) *AND { } } - operands.add(reduced) + operands.Add(reduced) } - vs := operands.values() + vs := operands.Values() opnds := make([]SemanticContext, len(vs)) for i, v := range vs { opnds[i] = v.(SemanticContext) @@ -334,21 +345,21 @@ type OR struct { func NewOR(a, b SemanticContext) *OR { - operands := NewSet(nil, nil) + operands := NewArray2DHashSet(nil, nil) if aa, ok := a.(*OR); ok { for _, o := range aa.opnds { - operands.add(o) + operands.Add(o) } } else { - operands.add(a) + operands.Add(a) } if ba, ok := b.(*OR); ok { for _, o := range ba.opnds { - operands.add(o) + operands.Add(o) } } else { - operands.add(b) + operands.Add(b) } precedencePredicates := PrecedencePredicatefilterPrecedencePredicates(operands) if len(precedencePredicates) > 0 { @@ -361,10 +372,10 @@ func NewOR(a, b SemanticContext) *OR { } } - operands.add(reduced) + operands.Add(reduced) } - vs := operands.values() + vs := operands.Values() opnds := make([]SemanticContext, len(vs)) for i, v := range vs { diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/transition.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/transition.go index eb7e57e9a..53056bd74 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/transition.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/transition.go @@ -7,6 +7,7 @@ package antlr import ( "fmt" "strconv" + "strings" ) // atom, set, epsilon, action, predicate, rule transitions. @@ -236,7 +237,13 @@ func (t *RangeTransition) Matches(symbol, minVocabSymbol, maxVocabSymbol int) bo } func (t *RangeTransition) String() string { - return "'" + string(t.start) + "'..'" + string(t.stop) + "'" + var sb strings.Builder + sb.WriteByte('\'') + sb.WriteRune(rune(t.start)) + sb.WriteString("'..'") + sb.WriteRune(rune(t.stop)) + sb.WriteByte('\'') + return sb.String() } type AbstractPredicateTransition interface { diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/utils.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/utils.go index bba2ffae7..9c7d0a6cd 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/utils.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/utils.go @@ -47,35 +47,6 @@ func (s *IntStack) Push(e int) { *s = append(*s, e) } -type Set struct { - data map[int][]interface{} - hashcodeFunction func(interface{}) int - equalsFunction func(interface{}, interface{}) bool -} - -func NewSet( - hashcodeFunction func(interface{}) int, - equalsFunction func(interface{}, interface{}) bool) *Set { - - s := new(Set) - - s.data = make(map[int][]interface{}) - - if hashcodeFunction != nil { - s.hashcodeFunction = hashcodeFunction - } else { - s.hashcodeFunction = standardHashFunction - } - - if equalsFunction == nil { - s.equalsFunction = standardEqualsFunction - } else { - s.equalsFunction = equalsFunction - } - - return s -} - func standardEqualsFunction(a interface{}, b interface{}) bool { ac, oka := a.(comparable) @@ -100,72 +71,6 @@ type hasher interface { hash() int } -func (s *Set) length() int { - return len(s.data) -} - -func (s *Set) add(value interface{}) interface{} { - - key := s.hashcodeFunction(value) - - values := s.data[key] - - if s.data[key] != nil { - for i := 0; i < len(values); i++ { - if s.equalsFunction(value, values[i]) { - return values[i] - } - } - - s.data[key] = append(s.data[key], value) - return value - } - - v := make([]interface{}, 1, 10) - v[0] = value - s.data[key] = v - - return value -} - -func (s *Set) contains(value interface{}) bool { - - key := s.hashcodeFunction(value) - - values := s.data[key] - - if s.data[key] != nil { - for i := 0; i < len(values); i++ { - if s.equalsFunction(value, values[i]) { - return true - } - } - } - return false -} - -func (s *Set) values() []interface{} { - var l []interface{} - - for _, v := range s.data { - l = append(l, v...) - } - - return l -} - -func (s *Set) String() string { - r := "" - - for _, av := range s.data { - for _, v := range av { - r += fmt.Sprint(v) - } - } - - return r -} - type BitSet struct { data map[int]bool } @@ -353,65 +258,38 @@ func PrintArrayJavaStyle(sa []string) string { return buffer.String() } -// The following routines were lifted from bits.rotate* available in Go 1.9. - -const uintSize = 32 << (^uint(0) >> 32 & 1) // 32 or 64 - -// rotateLeft returns the value of x rotated left by (k mod UintSize) bits. -// To rotate x right by k bits, call RotateLeft(x, -k). -func rotateLeft(x uint, k int) uint { - if uintSize == 32 { - return uint(rotateLeft32(uint32(x), k)) - } - return uint(rotateLeft64(uint64(x), k)) -} - -// rotateLeft32 returns the value of x rotated left by (k mod 32) bits. -func rotateLeft32(x uint32, k int) uint32 { - const n = 32 - s := uint(k) & (n - 1) - return x<>(n-s) -} - -// rotateLeft64 returns the value of x rotated left by (k mod 64) bits. -func rotateLeft64(x uint64, k int) uint64 { - const n = 64 - s := uint(k) & (n - 1) - return x<>(n-s) -} - - // murmur hash -const ( - c1_32 uint = 0xCC9E2D51 - c2_32 uint = 0x1B873593 - n1_32 uint = 0xE6546B64 -) - func murmurInit(seed int) int { return seed } -func murmurUpdate(h1 int, k1 int) int { - var k1u uint - k1u = uint(k1) * c1_32 - k1u = rotateLeft(k1u, 15) - k1u *= c2_32 +func murmurUpdate(h int, value int) int { + const c1 uint32 = 0xCC9E2D51 + const c2 uint32 = 0x1B873593 + const r1 uint32 = 15 + const r2 uint32 = 13 + const m uint32 = 5 + const n uint32 = 0xE6546B64 - var h1u = uint(h1) ^ k1u - k1u = rotateLeft(k1u, 13) - h1u = h1u*5 + 0xe6546b64 - return int(h1u) + k := uint32(value) + k *= c1 + k = (k << r1) | (k >> (32 - r1)) + k *= c2 + + hash := uint32(h) ^ k + hash = (hash << r2) | (hash >> (32 - r2)) + hash = hash*m + n + return int(hash) } -func murmurFinish(h1 int, numberOfWords int) int { - var h1u uint = uint(h1) - h1u ^= uint(numberOfWords * 4) - h1u ^= h1u >> 16 - h1u *= uint(0x85ebca6b) - h1u ^= h1u >> 13 - h1u *= 0xc2b2ae35 - h1u ^= h1u >> 16 +func murmurFinish(h int, numberOfWords int) int { + var hash = uint32(h) + hash ^= uint32(numberOfWords) << 2 + hash ^= hash >> 16 + hash *= 0x85ebca6b + hash ^= hash >> 13 + hash *= 0xc2b2ae35 + hash ^= hash >> 16 - return int(h1u) + return int(hash) } diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/utils_set.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/utils_set.go new file mode 100644 index 000000000..9caa78b8c --- /dev/null +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/utils_set.go @@ -0,0 +1,237 @@ +package antlr + +import "math" + +const ( + _initalCapacity = 16 + _initalBucketCapacity = 8 + _loadFactor = 0.75 +) + +var _ Set = (*Array2DHashSet)(nil) + +type Set interface { + Add(value interface{}) (added interface{}) + Len() int + Get(value interface{}) (found interface{}) + Contains(value interface{}) bool + Values() []interface{} + Each(f func(interface{}) bool) +} + +type Array2DHashSet struct { + buckets [][]interface{} + hashcodeFunction func(interface{}) int + equalsFunction func(interface{}, interface{}) bool + + n int // How many elements in set + threshold int // when to expand + + currentPrime int // jump by 4 primes each expand or whatever + initialBucketCapacity int +} + +func (as *Array2DHashSet) Each(f func(interface{}) bool) { + if as.Len() < 1 { + return + } + + for _, bucket := range as.buckets { + for _, o := range bucket { + if o == nil { + break + } + if !f(o) { + return + } + } + } +} + +func (as *Array2DHashSet) Values() []interface{} { + if as.Len() < 1 { + return nil + } + + values := make([]interface{}, 0, as.Len()) + as.Each(func(i interface{}) bool { + values = append(values, i) + return true + }) + return values +} + +func (as *Array2DHashSet) Contains(value interface{}) bool { + return as.Get(value) != nil +} + +func (as *Array2DHashSet) Add(value interface{}) interface{} { + if as.n > as.threshold { + as.expand() + } + return as.innerAdd(value) +} + +func (as *Array2DHashSet) expand() { + old := as.buckets + + as.currentPrime += 4 + + var ( + newCapacity = len(as.buckets) << 1 + newTable = as.createBuckets(newCapacity) + newBucketLengths = make([]int, len(newTable)) + ) + + as.buckets = newTable + as.threshold = int(float64(newCapacity) * _loadFactor) + + for _, bucket := range old { + if bucket == nil { + continue + } + + for _, o := range bucket { + if o == nil { + break + } + + b := as.getBuckets(o) + bucketLength := newBucketLengths[b] + var newBucket []interface{} + if bucketLength == 0 { + // new bucket + newBucket = as.createBucket(as.initialBucketCapacity) + newTable[b] = newBucket + } else { + newBucket = newTable[b] + if bucketLength == len(newBucket) { + // expand + newBucketCopy := make([]interface{}, len(newBucket)<<1) + copy(newBucketCopy[:bucketLength], newBucket) + newBucket = newBucketCopy + newTable[b] = newBucket + } + } + + newBucket[bucketLength] = o + newBucketLengths[b]++ + } + } +} + +func (as *Array2DHashSet) Len() int { + return as.n +} + +func (as *Array2DHashSet) Get(o interface{}) interface{} { + if o == nil { + return nil + } + + b := as.getBuckets(o) + bucket := as.buckets[b] + if bucket == nil { // no bucket + return nil + } + + for _, e := range bucket { + if e == nil { + return nil // empty slot; not there + } + if as.equalsFunction(e, o) { + return e + } + } + + return nil +} + +func (as *Array2DHashSet) innerAdd(o interface{}) interface{} { + b := as.getBuckets(o) + + bucket := as.buckets[b] + + // new bucket + if bucket == nil { + bucket = as.createBucket(as.initialBucketCapacity) + bucket[0] = o + + as.buckets[b] = bucket + as.n++ + return o + } + + // look for it in bucket + for i := 0; i < len(bucket); i++ { + existing := bucket[i] + if existing == nil { // empty slot; not there, add. + bucket[i] = o + as.n++ + return o + } + + if as.equalsFunction(existing, o) { // found existing, quit + return existing + } + } + + // full bucket, expand and add to end + oldLength := len(bucket) + bucketCopy := make([]interface{}, oldLength<<1) + copy(bucketCopy[:oldLength], bucket) + bucket = bucketCopy + as.buckets[b] = bucket + bucket[oldLength] = o + as.n++ + return o +} + +func (as *Array2DHashSet) getBuckets(value interface{}) int { + hash := as.hashcodeFunction(value) + return hash & (len(as.buckets) - 1) +} + +func (as *Array2DHashSet) createBuckets(cap int) [][]interface{} { + return make([][]interface{}, cap) +} + +func (as *Array2DHashSet) createBucket(cap int) []interface{} { + return make([]interface{}, cap) +} + +func NewArray2DHashSetWithCap( + hashcodeFunction func(interface{}) int, + equalsFunction func(interface{}, interface{}) bool, + initCap int, + initBucketCap int, +) *Array2DHashSet { + if hashcodeFunction == nil { + hashcodeFunction = standardHashFunction + } + + if equalsFunction == nil { + equalsFunction = standardEqualsFunction + } + + ret := &Array2DHashSet{ + hashcodeFunction: hashcodeFunction, + equalsFunction: equalsFunction, + + n: 0, + threshold: int(math.Floor(_initalCapacity * _loadFactor)), + + currentPrime: 1, + initialBucketCapacity: initBucketCap, + } + + ret.buckets = ret.createBuckets(initCap) + return ret +} + +func NewArray2DHashSet( + hashcodeFunction func(interface{}) int, + equalsFunction func(interface{}, interface{}) bool, +) *Array2DHashSet { + return NewArray2DHashSetWithCap(hashcodeFunction, equalsFunction, _initalCapacity, _initalBucketCapacity) +} diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/CESQLLexer.g4 b/vendor/github.com/cloudevents/sdk-go/sql/v2/CESQLLexer.g4 new file mode 100644 index 000000000..a889c058a --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/CESQLLexer.g4 @@ -0,0 +1,79 @@ +lexer grammar CESQLLexer; + +// NOTE: +// This grammar is case-sensitive, although CESQL keywords are case-insensitive. +// In order to implement case-insensitivity, check out +// https://github.com/antlr/antlr4/blob/master/doc/case-insensitive-lexing.md#custom-character-streams-approach + +// Skip tab, carriage return and newlines + +SPACE: [ \t\r\n]+ -> skip; + +// Fragments for Literal primitives + +fragment ID_LITERAL: [a-zA-Z0-9]+; +fragment DQUOTA_STRING: '"' ( '\\'. | '""' | ~('"'| '\\') )* '"'; +fragment SQUOTA_STRING: '\'' ('\\'. | '\'\'' | ~('\'' | '\\'))* '\''; +fragment INT_DIGIT: [0-9]; +fragment FN_LITERAL: [A-Z] [A-Z_]*; + +// Constructors symbols + +LR_BRACKET: '('; +RR_BRACKET: ')'; +COMMA: ','; +SINGLE_QUOTE_SYMB: '\''; +DOUBLE_QUOTE_SYMB: '"'; + +fragment QUOTE_SYMB + : SINGLE_QUOTE_SYMB | DOUBLE_QUOTE_SYMB + ; + +// Operators +// - Logic + +AND: 'AND'; +OR: 'OR'; +XOR: 'XOR'; +NOT: 'NOT'; + +// - Arithmetics + +STAR: '*'; +DIVIDE: '/'; +MODULE: '%'; +PLUS: '+'; +MINUS: '-'; + +// - Comparison + +EQUAL: '='; +NOT_EQUAL: '!='; +GREATER: '>'; +GREATER_OR_EQUAL: '>='; +LESS: '<'; +LESS_GREATER: '<>'; +LESS_OR_EQUAL: '<='; + +// Like, exists, in + +LIKE: 'LIKE'; +EXISTS: 'EXISTS'; +IN: 'IN'; + +// Booleans + +TRUE: 'TRUE'; +FALSE: 'FALSE'; + +// Literals + +DQUOTED_STRING_LITERAL: DQUOTA_STRING; +SQUOTED_STRING_LITERAL: SQUOTA_STRING; +INTEGER_LITERAL: INT_DIGIT+; + +// Identifiers + +IDENTIFIER: [a-zA-Z]+; +IDENTIFIER_WITH_NUMBER: [a-zA-Z0-9]+; +FUNCTION_IDENTIFIER_WITH_UNDERSCORE: [A-Z] [A-Z_]*; diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/CESQLParser.g4 b/vendor/github.com/cloudevents/sdk-go/sql/v2/CESQLParser.g4 new file mode 100644 index 000000000..abab0bac8 --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/CESQLParser.g4 @@ -0,0 +1,62 @@ +grammar CESQLParser; + +import CESQLLexer; + +// Entrypoint +cesql: expression EOF; + +// Structure of operations, function invocations and expression +expression + : functionIdentifier functionParameterList #functionInvocationExpression + // unary operators are the highest priority + | NOT expression #unaryLogicExpression + | MINUS expression # unaryNumericExpression + // LIKE, EXISTS and IN takes precedence over all the other binary operators + | expression NOT? LIKE stringLiteral #likeExpression + | EXISTS identifier #existsExpression + | expression NOT? IN setExpression #inExpression + // Numeric operations + | expression (STAR | DIVIDE | MODULE) expression #binaryMultiplicativeExpression + | expression (PLUS | MINUS) expression #binaryAdditiveExpression + // Comparison operations + | expression (EQUAL | NOT_EQUAL | LESS_GREATER | GREATER_OR_EQUAL | LESS_OR_EQUAL | LESS | GREATER) expression #binaryComparisonExpression + // Logic operations + | expression (AND | OR | XOR) expression #binaryLogicExpression + // Subexpressions and atoms + | LR_BRACKET expression RR_BRACKET #subExpression + | atom #atomExpression + ; + +atom + : booleanLiteral #booleanAtom + | integerLiteral #integerAtom + | stringLiteral #stringAtom + | identifier #identifierAtom + ; + +// Identifiers + +identifier + : (IDENTIFIER | IDENTIFIER_WITH_NUMBER) + ; +functionIdentifier + : (IDENTIFIER | FUNCTION_IDENTIFIER_WITH_UNDERSCORE) + ; + +// Literals + +booleanLiteral: (TRUE | FALSE); +stringLiteral: (DQUOTED_STRING_LITERAL | SQUOTED_STRING_LITERAL); +integerLiteral: INTEGER_LITERAL; + +// Functions + +functionParameterList + : LR_BRACKET ( expression ( COMMA expression )* )? RR_BRACKET + ; + +// Sets + +setExpression + : LR_BRACKET expression ( COMMA expression )* RR_BRACKET // Empty sets are not allowed + ; diff --git a/third_party/VENDOR-LICENSE/github.com/go-openapi/spec/LICENSE b/vendor/github.com/cloudevents/sdk-go/sql/v2/LICENSE similarity index 99% rename from third_party/VENDOR-LICENSE/github.com/go-openapi/spec/LICENSE rename to vendor/github.com/cloudevents/sdk-go/sql/v2/LICENSE index d64569567..261eeb9e9 100644 --- a/third_party/VENDOR-LICENSE/github.com/go-openapi/spec/LICENSE +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/LICENSE @@ -1,4 +1,3 @@ - Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/Makefile b/vendor/github.com/cloudevents/sdk-go/sql/v2/Makefile new file mode 100644 index 000000000..e69de29bb diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/README.md b/vendor/github.com/cloudevents/sdk-go/sql/v2/README.md new file mode 100644 index 000000000..179de0722 --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/README.md @@ -0,0 +1,32 @@ +# CloudEvents Expression Language Go implementation + +CloudEvents Expression Language implementation. + +Note: this package is a work in progress, APIs might break in future releases. + +## User guide + +To start using it: + +```go +import cesqlparser "github.com/cloudevents/sdk-go/sql/v2/parser" + +// Parse the expression +expression, err := cesqlparser.Parse("subject = 'Hello world'") + +// Res can be either int32, bool or string +res, err := expression.Evaluate(event) +``` + +## Development guide + +To regenerate the parser, make sure you have [ANTLR4 installed](https://github.com/antlr/antlr4/blob/master/doc/getting-started.md) and then run: + +```shell +antlr4 -Dlanguage=Go -package gen -o gen -visitor -no-listener CESQLParser.g4 +``` + +Then you need to run this sed command as a workaround until this ANTLR [issue](https://github.com/antlr/antlr4/issues/2433) is resolved. Without this, building for 32bit platforms will throw an int overflow error: +```shell +sed -i 's/(1< y + }, + } +} + +func NewGreaterOrEqualExpression(left cesql.Expression, right cesql.Expression) cesql.Expression { + return integerComparisonExpression{ + baseBinaryExpression: baseBinaryExpression{ + left: left, + right: right, + }, + fn: func(x, y int32) bool { + return x >= y + }, + } +} diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/like_expression.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/like_expression.go new file mode 100644 index 000000000..236c15caf --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/like_expression.go @@ -0,0 +1,96 @@ +/* + Copyright 2021 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +package expression + +import ( + "regexp" + "strings" + + cesql "github.com/cloudevents/sdk-go/sql/v2" + "github.com/cloudevents/sdk-go/sql/v2/utils" + cloudevents "github.com/cloudevents/sdk-go/v2" +) + +type likeExpression struct { + baseUnaryExpression + pattern *regexp.Regexp +} + +func (l likeExpression) Evaluate(event cloudevents.Event) (interface{}, error) { + val, err := l.child.Evaluate(event) + if err != nil { + return nil, err + } + + val, err = utils.Cast(val, cesql.StringType) + if err != nil { + return nil, err + } + + return l.pattern.MatchString(val.(string)), nil +} + +func NewLikeExpression(child cesql.Expression, pattern string) (cesql.Expression, error) { + // Converting to regex is not the most performant impl, but it works + p, err := convertLikePatternToRegex(pattern) + if err != nil { + return nil, err + } + + return likeExpression{ + baseUnaryExpression: baseUnaryExpression{ + child: child, + }, + pattern: p, + }, nil +} + +func convertLikePatternToRegex(pattern string) (*regexp.Regexp, error) { + var chunks []string + chunks = append(chunks, "^") + + var chunk strings.Builder + + for i := 0; i < len(pattern); i++ { + if pattern[i] == '\\' && i < len(pattern)-1 { + if pattern[i+1] == '%' { + // \% case + chunk.WriteRune('%') + chunks = append(chunks, "\\Q"+chunk.String()+"\\E") + chunk.Reset() + i++ + continue + } else if pattern[i+1] == '_' { + // \_ case + chunk.WriteRune('_') + chunks = append(chunks, "\\Q"+chunk.String()+"\\E") + chunk.Reset() + i++ + continue + } + } else if pattern[i] == '_' { + // replace with . + chunks = append(chunks, "\\Q"+chunk.String()+"\\E") + chunk.Reset() + chunks = append(chunks, ".") + } else if pattern[i] == '%' { + // replace with .* + chunks = append(chunks, "\\Q"+chunk.String()+"\\E") + chunk.Reset() + chunks = append(chunks, ".*") + } else { + chunk.WriteByte(pattern[i]) + } + } + + if chunk.Len() != 0 { + chunks = append(chunks, "\\Q"+chunk.String()+"\\E") + } + + chunks = append(chunks, "$") + + return regexp.Compile(strings.Join(chunks, "")) +} diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/literal_expression.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/literal_expression.go new file mode 100644 index 000000000..5c139fc8c --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/literal_expression.go @@ -0,0 +1,23 @@ +/* + Copyright 2021 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +package expression + +import ( + cesql "github.com/cloudevents/sdk-go/sql/v2" + cloudevents "github.com/cloudevents/sdk-go/v2" +) + +type literalExpression struct { + value interface{} +} + +func (l literalExpression) Evaluate(event cloudevents.Event) (interface{}, error) { + return l.value, nil +} + +func NewLiteralExpression(value interface{}) cesql.Expression { + return literalExpression{value: value} +} diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/logic_expressions.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/logic_expressions.go new file mode 100644 index 000000000..5c332a5f9 --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/logic_expressions.go @@ -0,0 +1,77 @@ +/* + Copyright 2021 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +package expression + +import ( + cesql "github.com/cloudevents/sdk-go/sql/v2" + "github.com/cloudevents/sdk-go/sql/v2/utils" + cloudevents "github.com/cloudevents/sdk-go/v2" +) + +type logicExpression struct { + baseBinaryExpression + fn func(x, y bool) bool +} + +func (s logicExpression) Evaluate(event cloudevents.Event) (interface{}, error) { + leftVal, err := s.left.Evaluate(event) + if err != nil { + return nil, err + } + + rightVal, err := s.right.Evaluate(event) + if err != nil { + return nil, err + } + + leftVal, err = utils.Cast(leftVal, cesql.BooleanType) + if err != nil { + return nil, err + } + + rightVal, err = utils.Cast(rightVal, cesql.BooleanType) + if err != nil { + return nil, err + } + + return s.fn(leftVal.(bool), rightVal.(bool)), nil +} + +func NewAndExpression(left cesql.Expression, right cesql.Expression) cesql.Expression { + return logicExpression{ + baseBinaryExpression: baseBinaryExpression{ + left: left, + right: right, + }, + fn: func(x, y bool) bool { + return x && y + }, + } +} + +func NewOrExpression(left cesql.Expression, right cesql.Expression) cesql.Expression { + return logicExpression{ + baseBinaryExpression: baseBinaryExpression{ + left: left, + right: right, + }, + fn: func(x, y bool) bool { + return x || y + }, + } +} + +func NewXorExpression(left cesql.Expression, right cesql.Expression) cesql.Expression { + return logicExpression{ + baseBinaryExpression: baseBinaryExpression{ + left: left, + right: right, + }, + fn: func(x, y bool) bool { + return x != y + }, + } +} diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/math_expressions.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/math_expressions.go new file mode 100644 index 000000000..d03782011 --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/math_expressions.go @@ -0,0 +1,109 @@ +/* + Copyright 2021 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +package expression + +import ( + "errors" + + cesql "github.com/cloudevents/sdk-go/sql/v2" + "github.com/cloudevents/sdk-go/sql/v2/utils" + cloudevents "github.com/cloudevents/sdk-go/v2" +) + +type mathExpression struct { + baseBinaryExpression + fn func(x, y int32) (int32, error) +} + +func (s mathExpression) Evaluate(event cloudevents.Event) (interface{}, error) { + leftVal, err := s.left.Evaluate(event) + if err != nil { + return nil, err + } + + rightVal, err := s.right.Evaluate(event) + if err != nil { + return nil, err + } + + leftVal, err = utils.Cast(leftVal, cesql.IntegerType) + if err != nil { + return nil, err + } + + rightVal, err = utils.Cast(rightVal, cesql.IntegerType) + if err != nil { + return nil, err + } + + return s.fn(leftVal.(int32), rightVal.(int32)) +} + +func NewSumExpression(left cesql.Expression, right cesql.Expression) cesql.Expression { + return mathExpression{ + baseBinaryExpression: baseBinaryExpression{ + left: left, + right: right, + }, + fn: func(x, y int32) (int32, error) { + return x + y, nil + }, + } +} + +func NewDifferenceExpression(left cesql.Expression, right cesql.Expression) cesql.Expression { + return mathExpression{ + baseBinaryExpression: baseBinaryExpression{ + left: left, + right: right, + }, + fn: func(x, y int32) (int32, error) { + return x - y, nil + }, + } +} + +func NewMultiplicationExpression(left cesql.Expression, right cesql.Expression) cesql.Expression { + return mathExpression{ + baseBinaryExpression: baseBinaryExpression{ + left: left, + right: right, + }, + fn: func(x, y int32) (int32, error) { + return x * y, nil + }, + } +} + +func NewModuleExpression(left cesql.Expression, right cesql.Expression) cesql.Expression { + return mathExpression{ + baseBinaryExpression: baseBinaryExpression{ + left: left, + right: right, + }, + fn: func(x, y int32) (int32, error) { + if y == 0 { + return 0, errors.New("math error: division by zero") + } + return x % y, nil + }, + } +} + +func NewDivisionExpression(left cesql.Expression, right cesql.Expression) cesql.Expression { + return mathExpression{ + baseBinaryExpression: baseBinaryExpression{ + left: left, + right: right, + }, + fn: func(x, y int32) (int32, error) { + if y == 0 { + return 0, errors.New("math error: division by zero") + } + return x / y, nil + }, + } +} diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/negate_expression.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/negate_expression.go new file mode 100644 index 000000000..f917a83bf --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/negate_expression.go @@ -0,0 +1,32 @@ +/* + Copyright 2021 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +package expression + +import ( + cesql "github.com/cloudevents/sdk-go/sql/v2" + "github.com/cloudevents/sdk-go/sql/v2/utils" + cloudevents "github.com/cloudevents/sdk-go/v2" +) + +type negateExpression baseUnaryExpression + +func (l negateExpression) Evaluate(event cloudevents.Event) (interface{}, error) { + val, err := l.child.Evaluate(event) + if err != nil { + return nil, err + } + + val, err = utils.Cast(val, cesql.IntegerType) + if err != nil { + return nil, err + } + + return -(val.(int32)), nil +} + +func NewNegateExpression(child cesql.Expression) cesql.Expression { + return negateExpression{child: child} +} diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/not_expression.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/not_expression.go new file mode 100644 index 000000000..7f5e95b9f --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/not_expression.go @@ -0,0 +1,32 @@ +/* + Copyright 2021 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +package expression + +import ( + cesql "github.com/cloudevents/sdk-go/sql/v2" + "github.com/cloudevents/sdk-go/sql/v2/utils" + cloudevents "github.com/cloudevents/sdk-go/v2" +) + +type notExpression baseUnaryExpression + +func (l notExpression) Evaluate(event cloudevents.Event) (interface{}, error) { + val, err := l.child.Evaluate(event) + if err != nil { + return nil, err + } + + val, err = utils.Cast(val, cesql.BooleanType) + if err != nil { + return nil, err + } + + return !(val.(bool)), nil +} + +func NewNotExpression(child cesql.Expression) cesql.Expression { + return notExpression{child: child} +} diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/function.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/function.go new file mode 100644 index 000000000..1502a3d2f --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/function.go @@ -0,0 +1,17 @@ +/* + Copyright 2021 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +package v2 + +import cloudevents "github.com/cloudevents/sdk-go/v2" + +type Function interface { + Name() string + Arity() int + IsVariadic() bool + ArgType(index int) *Type + + Run(event cloudevents.Event, arguments []interface{}) (interface{}, error) +} diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/function/casting_functions.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/function/casting_functions.go new file mode 100644 index 000000000..91069de80 --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/function/casting_functions.go @@ -0,0 +1,57 @@ +/* + Copyright 2021 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +package function + +import ( + cesql "github.com/cloudevents/sdk-go/sql/v2" + "github.com/cloudevents/sdk-go/sql/v2/utils" + cloudevents "github.com/cloudevents/sdk-go/v2" +) + +var IntFunction function = function{ + name: "INT", + fixedArgs: []cesql.Type{cesql.AnyType}, + variadicArgs: nil, + fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { + return utils.Cast(i[0], cesql.IntegerType) + }, +} + +var BoolFunction function = function{ + name: "BOOL", + fixedArgs: []cesql.Type{cesql.AnyType}, + variadicArgs: nil, + fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { + return utils.Cast(i[0], cesql.BooleanType) + }, +} + +var StringFunction function = function{ + name: "STRING", + fixedArgs: []cesql.Type{cesql.AnyType}, + variadicArgs: nil, + fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { + return utils.Cast(i[0], cesql.StringType) + }, +} + +var IsIntFunction function = function{ + name: "IS_INT", + fixedArgs: []cesql.Type{cesql.AnyType}, + variadicArgs: nil, + fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { + return utils.CanCast(i[0], cesql.IntegerType), nil + }, +} + +var IsBoolFunction function = function{ + name: "IS_BOOL", + fixedArgs: []cesql.Type{cesql.AnyType}, + variadicArgs: nil, + fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { + return utils.CanCast(i[0], cesql.BooleanType), nil + }, +} diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/function/function.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/function/function.go new file mode 100644 index 000000000..4ad61faed --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/function/function.go @@ -0,0 +1,41 @@ +/* + Copyright 2021 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +package function + +import ( + cesql "github.com/cloudevents/sdk-go/sql/v2" + cloudevents "github.com/cloudevents/sdk-go/v2" +) + +type function struct { + name string + fixedArgs []cesql.Type + variadicArgs *cesql.Type + fn func(cloudevents.Event, []interface{}) (interface{}, error) +} + +func (f function) Name() string { + return f.name +} + +func (f function) Arity() int { + return len(f.fixedArgs) +} + +func (f function) IsVariadic() bool { + return f.variadicArgs != nil +} + +func (f function) ArgType(index int) *cesql.Type { + if index < len(f.fixedArgs) { + return &f.fixedArgs[index] + } + return f.variadicArgs +} + +func (f function) Run(event cloudevents.Event, arguments []interface{}) (interface{}, error) { + return f.fn(event, arguments) +} diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/function/integer_functions.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/function/integer_functions.go new file mode 100644 index 000000000..4aaf64f22 --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/function/integer_functions.go @@ -0,0 +1,24 @@ +/* + Copyright 2021 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +package function + +import ( + cesql "github.com/cloudevents/sdk-go/sql/v2" + cloudevents "github.com/cloudevents/sdk-go/v2" +) + +var AbsFunction function = function{ + name: "ABS", + fixedArgs: []cesql.Type{cesql.IntegerType}, + variadicArgs: nil, + fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { + x := i[0].(int32) + if x < 0 { + return -x, nil + } + return x, nil + }, +} diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/function/string_functions.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/function/string_functions.go new file mode 100644 index 000000000..2d0d7e4a9 --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/function/string_functions.go @@ -0,0 +1,177 @@ +/* + Copyright 2021 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +package function + +import ( + "fmt" + "strings" + + cesql "github.com/cloudevents/sdk-go/sql/v2" + cloudevents "github.com/cloudevents/sdk-go/v2" +) + +var LengthFunction function = function{ + name: "LENGTH", + fixedArgs: []cesql.Type{cesql.StringType}, + variadicArgs: nil, + fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { + return int32(len(i[0].(string))), nil + }, +} + +var ConcatFunction function = function{ + name: "CONCAT", + variadicArgs: cesql.TypePtr(cesql.StringType), + fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { + var sb strings.Builder + for _, v := range i { + sb.WriteString(v.(string)) + } + return sb.String(), nil + }, +} + +var ConcatWSFunction function = function{ + name: "CONCAT_WS", + fixedArgs: []cesql.Type{cesql.StringType}, + variadicArgs: cesql.TypePtr(cesql.StringType), + fn: func(event cloudevents.Event, args []interface{}) (interface{}, error) { + if len(args) == 1 { + return "", nil + } + separator := args[0].(string) + + var sb strings.Builder + for i := 1; i < len(args)-1; i++ { + sb.WriteString(args[i].(string)) + sb.WriteString(separator) + } + sb.WriteString(args[len(args)-1].(string)) + return sb.String(), nil + }, +} + +var LowerFunction function = function{ + name: "LOWER", + fixedArgs: []cesql.Type{cesql.StringType}, + fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { + return strings.ToLower(i[0].(string)), nil + }, +} + +var UpperFunction function = function{ + name: "UPPER", + fixedArgs: []cesql.Type{cesql.StringType}, + fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { + return strings.ToUpper(i[0].(string)), nil + }, +} + +var TrimFunction function = function{ + name: "TRIM", + fixedArgs: []cesql.Type{cesql.StringType}, + fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { + return strings.TrimSpace(i[0].(string)), nil + }, +} + +var LeftFunction function = function{ + name: "LEFT", + fixedArgs: []cesql.Type{cesql.StringType, cesql.IntegerType}, + fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { + str := i[0].(string) + y := int(i[1].(int32)) + + if y > len(str) { + return str, nil + } + + if y < 0 { + return nil, fmt.Errorf("LEFT y argument is < 0: %d", y) + } + + return str[0:y], nil + }, +} + +var RightFunction function = function{ + name: "RIGHT", + fixedArgs: []cesql.Type{cesql.StringType, cesql.IntegerType}, + fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { + str := i[0].(string) + y := int(i[1].(int32)) + + if y > len(str) { + return str, nil + } + + if y < 0 { + return nil, fmt.Errorf("RIGHT y argument is < 0: %d", y) + } + + return str[len(str)-y:], nil + }, +} + +var SubstringFunction function = function{ + name: "SUBSTRING", + fixedArgs: []cesql.Type{cesql.StringType, cesql.IntegerType}, + fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { + str := i[0].(string) + pos := int(i[1].(int32)) + + if pos == 0 { + return "", nil + } + + if pos < -len(str) || pos > len(str) { + return "", fmt.Errorf("SUBSTRING invalid pos argument: %d", pos) + } + + var beginning int + if pos < 0 { + beginning = len(str) + pos + } else { + beginning = pos - 1 + } + + return str[beginning:], nil + }, +} + +var SubstringWithLengthFunction function = function{ + name: "SUBSTRING", + fixedArgs: []cesql.Type{cesql.StringType, cesql.IntegerType, cesql.IntegerType}, + fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { + str := i[0].(string) + pos := int(i[1].(int32)) + length := int(i[2].(int32)) + + if pos == 0 { + return "", nil + } + + if pos < -len(str) || pos > len(str) { + return "", fmt.Errorf("SUBSTRING invalid pos argument: %d", pos) + } + + var beginning int + if pos < 0 { + beginning = len(str) + pos + } else { + beginning = pos - 1 + } + + var end int + if beginning+length > len(str) { + end = len(str) + } else { + end = beginning + length + } + + return str[beginning:end], nil + }, +} diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/CESQLParser.interp b/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/CESQLParser.interp new file mode 100644 index 000000000..2727c21b9 --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/CESQLParser.interp @@ -0,0 +1,87 @@ +token literal names: +null +null +'(' +')' +',' +'\'' +'"' +'AND' +'OR' +'XOR' +'NOT' +'*' +'/' +'%' +'+' +'-' +'=' +'!=' +'>' +'>=' +'<' +'<>' +'<=' +'LIKE' +'EXISTS' +'IN' +'TRUE' +'FALSE' +null +null +null +null +null +null + +token symbolic names: +null +SPACE +LR_BRACKET +RR_BRACKET +COMMA +SINGLE_QUOTE_SYMB +DOUBLE_QUOTE_SYMB +AND +OR +XOR +NOT +STAR +DIVIDE +MODULE +PLUS +MINUS +EQUAL +NOT_EQUAL +GREATER +GREATER_OR_EQUAL +LESS +LESS_GREATER +LESS_OR_EQUAL +LIKE +EXISTS +IN +TRUE +FALSE +DQUOTED_STRING_LITERAL +SQUOTED_STRING_LITERAL +INTEGER_LITERAL +IDENTIFIER +IDENTIFIER_WITH_NUMBER +FUNCTION_IDENTIFIER_WITH_UNDERSCORE + +rule names: +cesql +expression +atom +identifier +functionIdentifier +booleanLiteral +stringLiteral +integerLiteral +functionParameterList +setExpression + + +atn: +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 35, 112, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 41, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 57, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 63, 10, 3, 3, 3, 3, 3, 7, 3, 67, 10, 3, 12, 3, 14, 3, 70, 11, 3, 3, 4, 3, 4, 3, 4, 3, 4, 5, 4, 76, 10, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 7, 10, 92, 10, 10, 12, 10, 14, 10, 95, 11, 10, 5, 10, 97, 10, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 7, 11, 105, 10, 11, 12, 11, 14, 11, 108, 11, 11, 3, 11, 3, 11, 3, 11, 2, 3, 4, 12, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 2, 10, 3, 2, 13, 15, 3, 2, 16, 17, 3, 2, 18, 24, 3, 2, 9, 11, 3, 2, 33, 34, 4, 2, 33, 33, 35, 35, 3, 2, 28, 29, 3, 2, 30, 31, 2, 120, 2, 22, 3, 2, 2, 2, 4, 40, 3, 2, 2, 2, 6, 75, 3, 2, 2, 2, 8, 77, 3, 2, 2, 2, 10, 79, 3, 2, 2, 2, 12, 81, 3, 2, 2, 2, 14, 83, 3, 2, 2, 2, 16, 85, 3, 2, 2, 2, 18, 87, 3, 2, 2, 2, 20, 100, 3, 2, 2, 2, 22, 23, 5, 4, 3, 2, 23, 24, 7, 2, 2, 3, 24, 3, 3, 2, 2, 2, 25, 26, 8, 3, 1, 2, 26, 27, 5, 10, 6, 2, 27, 28, 5, 18, 10, 2, 28, 41, 3, 2, 2, 2, 29, 30, 7, 12, 2, 2, 30, 41, 5, 4, 3, 13, 31, 32, 7, 17, 2, 2, 32, 41, 5, 4, 3, 12, 33, 34, 7, 26, 2, 2, 34, 41, 5, 8, 5, 2, 35, 36, 7, 4, 2, 2, 36, 37, 5, 4, 3, 2, 37, 38, 7, 5, 2, 2, 38, 41, 3, 2, 2, 2, 39, 41, 5, 6, 4, 2, 40, 25, 3, 2, 2, 2, 40, 29, 3, 2, 2, 2, 40, 31, 3, 2, 2, 2, 40, 33, 3, 2, 2, 2, 40, 35, 3, 2, 2, 2, 40, 39, 3, 2, 2, 2, 41, 68, 3, 2, 2, 2, 42, 43, 12, 8, 2, 2, 43, 44, 9, 2, 2, 2, 44, 67, 5, 4, 3, 9, 45, 46, 12, 7, 2, 2, 46, 47, 9, 3, 2, 2, 47, 67, 5, 4, 3, 8, 48, 49, 12, 6, 2, 2, 49, 50, 9, 4, 2, 2, 50, 67, 5, 4, 3, 7, 51, 52, 12, 5, 2, 2, 52, 53, 9, 5, 2, 2, 53, 67, 5, 4, 3, 5, 54, 56, 12, 11, 2, 2, 55, 57, 7, 12, 2, 2, 56, 55, 3, 2, 2, 2, 56, 57, 3, 2, 2, 2, 57, 58, 3, 2, 2, 2, 58, 59, 7, 25, 2, 2, 59, 67, 5, 14, 8, 2, 60, 62, 12, 9, 2, 2, 61, 63, 7, 12, 2, 2, 62, 61, 3, 2, 2, 2, 62, 63, 3, 2, 2, 2, 63, 64, 3, 2, 2, 2, 64, 65, 7, 27, 2, 2, 65, 67, 5, 20, 11, 2, 66, 42, 3, 2, 2, 2, 66, 45, 3, 2, 2, 2, 66, 48, 3, 2, 2, 2, 66, 51, 3, 2, 2, 2, 66, 54, 3, 2, 2, 2, 66, 60, 3, 2, 2, 2, 67, 70, 3, 2, 2, 2, 68, 66, 3, 2, 2, 2, 68, 69, 3, 2, 2, 2, 69, 5, 3, 2, 2, 2, 70, 68, 3, 2, 2, 2, 71, 76, 5, 12, 7, 2, 72, 76, 5, 16, 9, 2, 73, 76, 5, 14, 8, 2, 74, 76, 5, 8, 5, 2, 75, 71, 3, 2, 2, 2, 75, 72, 3, 2, 2, 2, 75, 73, 3, 2, 2, 2, 75, 74, 3, 2, 2, 2, 76, 7, 3, 2, 2, 2, 77, 78, 9, 6, 2, 2, 78, 9, 3, 2, 2, 2, 79, 80, 9, 7, 2, 2, 80, 11, 3, 2, 2, 2, 81, 82, 9, 8, 2, 2, 82, 13, 3, 2, 2, 2, 83, 84, 9, 9, 2, 2, 84, 15, 3, 2, 2, 2, 85, 86, 7, 32, 2, 2, 86, 17, 3, 2, 2, 2, 87, 96, 7, 4, 2, 2, 88, 93, 5, 4, 3, 2, 89, 90, 7, 6, 2, 2, 90, 92, 5, 4, 3, 2, 91, 89, 3, 2, 2, 2, 92, 95, 3, 2, 2, 2, 93, 91, 3, 2, 2, 2, 93, 94, 3, 2, 2, 2, 94, 97, 3, 2, 2, 2, 95, 93, 3, 2, 2, 2, 96, 88, 3, 2, 2, 2, 96, 97, 3, 2, 2, 2, 97, 98, 3, 2, 2, 2, 98, 99, 7, 5, 2, 2, 99, 19, 3, 2, 2, 2, 100, 101, 7, 4, 2, 2, 101, 106, 5, 4, 3, 2, 102, 103, 7, 6, 2, 2, 103, 105, 5, 4, 3, 2, 104, 102, 3, 2, 2, 2, 105, 108, 3, 2, 2, 2, 106, 104, 3, 2, 2, 2, 106, 107, 3, 2, 2, 2, 107, 109, 3, 2, 2, 2, 108, 106, 3, 2, 2, 2, 109, 110, 7, 5, 2, 2, 110, 21, 3, 2, 2, 2, 11, 40, 56, 62, 66, 68, 75, 93, 96, 106] \ No newline at end of file diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/CESQLParser.tokens b/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/CESQLParser.tokens new file mode 100644 index 000000000..913f0bc71 --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/CESQLParser.tokens @@ -0,0 +1,59 @@ +SPACE=1 +LR_BRACKET=2 +RR_BRACKET=3 +COMMA=4 +SINGLE_QUOTE_SYMB=5 +DOUBLE_QUOTE_SYMB=6 +AND=7 +OR=8 +XOR=9 +NOT=10 +STAR=11 +DIVIDE=12 +MODULE=13 +PLUS=14 +MINUS=15 +EQUAL=16 +NOT_EQUAL=17 +GREATER=18 +GREATER_OR_EQUAL=19 +LESS=20 +LESS_GREATER=21 +LESS_OR_EQUAL=22 +LIKE=23 +EXISTS=24 +IN=25 +TRUE=26 +FALSE=27 +DQUOTED_STRING_LITERAL=28 +SQUOTED_STRING_LITERAL=29 +INTEGER_LITERAL=30 +IDENTIFIER=31 +IDENTIFIER_WITH_NUMBER=32 +FUNCTION_IDENTIFIER_WITH_UNDERSCORE=33 +'('=2 +')'=3 +','=4 +'\''=5 +'"'=6 +'AND'=7 +'OR'=8 +'XOR'=9 +'NOT'=10 +'*'=11 +'/'=12 +'%'=13 +'+'=14 +'-'=15 +'='=16 +'!='=17 +'>'=18 +'>='=19 +'<'=20 +'<>'=21 +'<='=22 +'LIKE'=23 +'EXISTS'=24 +'IN'=25 +'TRUE'=26 +'FALSE'=27 diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/CESQLParserLexer.interp b/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/CESQLParserLexer.interp new file mode 100644 index 000000000..318204ece --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/CESQLParserLexer.interp @@ -0,0 +1,122 @@ +token literal names: +null +null +'(' +')' +',' +'\'' +'"' +'AND' +'OR' +'XOR' +'NOT' +'*' +'/' +'%' +'+' +'-' +'=' +'!=' +'>' +'>=' +'<' +'<>' +'<=' +'LIKE' +'EXISTS' +'IN' +'TRUE' +'FALSE' +null +null +null +null +null +null + +token symbolic names: +null +SPACE +LR_BRACKET +RR_BRACKET +COMMA +SINGLE_QUOTE_SYMB +DOUBLE_QUOTE_SYMB +AND +OR +XOR +NOT +STAR +DIVIDE +MODULE +PLUS +MINUS +EQUAL +NOT_EQUAL +GREATER +GREATER_OR_EQUAL +LESS +LESS_GREATER +LESS_OR_EQUAL +LIKE +EXISTS +IN +TRUE +FALSE +DQUOTED_STRING_LITERAL +SQUOTED_STRING_LITERAL +INTEGER_LITERAL +IDENTIFIER +IDENTIFIER_WITH_NUMBER +FUNCTION_IDENTIFIER_WITH_UNDERSCORE + +rule names: +SPACE +ID_LITERAL +DQUOTA_STRING +SQUOTA_STRING +INT_DIGIT +FN_LITERAL +LR_BRACKET +RR_BRACKET +COMMA +SINGLE_QUOTE_SYMB +DOUBLE_QUOTE_SYMB +QUOTE_SYMB +AND +OR +XOR +NOT +STAR +DIVIDE +MODULE +PLUS +MINUS +EQUAL +NOT_EQUAL +GREATER +GREATER_OR_EQUAL +LESS +LESS_GREATER +LESS_OR_EQUAL +LIKE +EXISTS +IN +TRUE +FALSE +DQUOTED_STRING_LITERAL +SQUOTED_STRING_LITERAL +INTEGER_LITERAL +IDENTIFIER +IDENTIFIER_WITH_NUMBER +FUNCTION_IDENTIFIER_WITH_UNDERSCORE + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN + +mode names: +DEFAULT_MODE + +atn: +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 35, 237, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 3, 2, 6, 2, 83, 10, 2, 13, 2, 14, 2, 84, 3, 2, 3, 2, 3, 3, 6, 3, 90, 10, 3, 13, 3, 14, 3, 91, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 7, 4, 100, 10, 4, 12, 4, 14, 4, 103, 11, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 7, 5, 113, 10, 5, 12, 5, 14, 5, 116, 11, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 7, 7, 124, 10, 7, 12, 7, 14, 7, 127, 11, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 13, 3, 13, 5, 13, 141, 10, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 6, 37, 217, 10, 37, 13, 37, 14, 37, 218, 3, 38, 6, 38, 222, 10, 38, 13, 38, 14, 38, 223, 3, 39, 6, 39, 227, 10, 39, 13, 39, 14, 39, 228, 3, 40, 3, 40, 7, 40, 233, 10, 40, 12, 40, 14, 40, 236, 11, 40, 2, 2, 41, 3, 3, 5, 2, 7, 2, 9, 2, 11, 2, 13, 2, 15, 4, 17, 5, 19, 6, 21, 7, 23, 8, 25, 2, 27, 9, 29, 10, 31, 11, 33, 12, 35, 13, 37, 14, 39, 15, 41, 16, 43, 17, 45, 18, 47, 19, 49, 20, 51, 21, 53, 22, 55, 23, 57, 24, 59, 25, 61, 26, 63, 27, 65, 28, 67, 29, 69, 30, 71, 31, 73, 32, 75, 33, 77, 34, 79, 35, 3, 2, 10, 5, 2, 11, 12, 15, 15, 34, 34, 5, 2, 50, 59, 67, 92, 99, 124, 4, 2, 36, 36, 94, 94, 4, 2, 41, 41, 94, 94, 3, 2, 50, 59, 3, 2, 67, 92, 4, 2, 67, 92, 97, 97, 4, 2, 67, 92, 99, 124, 2, 244, 2, 3, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 3, 82, 3, 2, 2, 2, 5, 89, 3, 2, 2, 2, 7, 93, 3, 2, 2, 2, 9, 106, 3, 2, 2, 2, 11, 119, 3, 2, 2, 2, 13, 121, 3, 2, 2, 2, 15, 128, 3, 2, 2, 2, 17, 130, 3, 2, 2, 2, 19, 132, 3, 2, 2, 2, 21, 134, 3, 2, 2, 2, 23, 136, 3, 2, 2, 2, 25, 140, 3, 2, 2, 2, 27, 142, 3, 2, 2, 2, 29, 146, 3, 2, 2, 2, 31, 149, 3, 2, 2, 2, 33, 153, 3, 2, 2, 2, 35, 157, 3, 2, 2, 2, 37, 159, 3, 2, 2, 2, 39, 161, 3, 2, 2, 2, 41, 163, 3, 2, 2, 2, 43, 165, 3, 2, 2, 2, 45, 167, 3, 2, 2, 2, 47, 169, 3, 2, 2, 2, 49, 172, 3, 2, 2, 2, 51, 174, 3, 2, 2, 2, 53, 177, 3, 2, 2, 2, 55, 179, 3, 2, 2, 2, 57, 182, 3, 2, 2, 2, 59, 185, 3, 2, 2, 2, 61, 190, 3, 2, 2, 2, 63, 197, 3, 2, 2, 2, 65, 200, 3, 2, 2, 2, 67, 205, 3, 2, 2, 2, 69, 211, 3, 2, 2, 2, 71, 213, 3, 2, 2, 2, 73, 216, 3, 2, 2, 2, 75, 221, 3, 2, 2, 2, 77, 226, 3, 2, 2, 2, 79, 230, 3, 2, 2, 2, 81, 83, 9, 2, 2, 2, 82, 81, 3, 2, 2, 2, 83, 84, 3, 2, 2, 2, 84, 82, 3, 2, 2, 2, 84, 85, 3, 2, 2, 2, 85, 86, 3, 2, 2, 2, 86, 87, 8, 2, 2, 2, 87, 4, 3, 2, 2, 2, 88, 90, 9, 3, 2, 2, 89, 88, 3, 2, 2, 2, 90, 91, 3, 2, 2, 2, 91, 89, 3, 2, 2, 2, 91, 92, 3, 2, 2, 2, 92, 6, 3, 2, 2, 2, 93, 101, 7, 36, 2, 2, 94, 95, 7, 94, 2, 2, 95, 100, 11, 2, 2, 2, 96, 97, 7, 36, 2, 2, 97, 100, 7, 36, 2, 2, 98, 100, 10, 4, 2, 2, 99, 94, 3, 2, 2, 2, 99, 96, 3, 2, 2, 2, 99, 98, 3, 2, 2, 2, 100, 103, 3, 2, 2, 2, 101, 99, 3, 2, 2, 2, 101, 102, 3, 2, 2, 2, 102, 104, 3, 2, 2, 2, 103, 101, 3, 2, 2, 2, 104, 105, 7, 36, 2, 2, 105, 8, 3, 2, 2, 2, 106, 114, 7, 41, 2, 2, 107, 108, 7, 94, 2, 2, 108, 113, 11, 2, 2, 2, 109, 110, 7, 41, 2, 2, 110, 113, 7, 41, 2, 2, 111, 113, 10, 5, 2, 2, 112, 107, 3, 2, 2, 2, 112, 109, 3, 2, 2, 2, 112, 111, 3, 2, 2, 2, 113, 116, 3, 2, 2, 2, 114, 112, 3, 2, 2, 2, 114, 115, 3, 2, 2, 2, 115, 117, 3, 2, 2, 2, 116, 114, 3, 2, 2, 2, 117, 118, 7, 41, 2, 2, 118, 10, 3, 2, 2, 2, 119, 120, 9, 6, 2, 2, 120, 12, 3, 2, 2, 2, 121, 125, 9, 7, 2, 2, 122, 124, 9, 8, 2, 2, 123, 122, 3, 2, 2, 2, 124, 127, 3, 2, 2, 2, 125, 123, 3, 2, 2, 2, 125, 126, 3, 2, 2, 2, 126, 14, 3, 2, 2, 2, 127, 125, 3, 2, 2, 2, 128, 129, 7, 42, 2, 2, 129, 16, 3, 2, 2, 2, 130, 131, 7, 43, 2, 2, 131, 18, 3, 2, 2, 2, 132, 133, 7, 46, 2, 2, 133, 20, 3, 2, 2, 2, 134, 135, 7, 41, 2, 2, 135, 22, 3, 2, 2, 2, 136, 137, 7, 36, 2, 2, 137, 24, 3, 2, 2, 2, 138, 141, 5, 21, 11, 2, 139, 141, 5, 23, 12, 2, 140, 138, 3, 2, 2, 2, 140, 139, 3, 2, 2, 2, 141, 26, 3, 2, 2, 2, 142, 143, 7, 67, 2, 2, 143, 144, 7, 80, 2, 2, 144, 145, 7, 70, 2, 2, 145, 28, 3, 2, 2, 2, 146, 147, 7, 81, 2, 2, 147, 148, 7, 84, 2, 2, 148, 30, 3, 2, 2, 2, 149, 150, 7, 90, 2, 2, 150, 151, 7, 81, 2, 2, 151, 152, 7, 84, 2, 2, 152, 32, 3, 2, 2, 2, 153, 154, 7, 80, 2, 2, 154, 155, 7, 81, 2, 2, 155, 156, 7, 86, 2, 2, 156, 34, 3, 2, 2, 2, 157, 158, 7, 44, 2, 2, 158, 36, 3, 2, 2, 2, 159, 160, 7, 49, 2, 2, 160, 38, 3, 2, 2, 2, 161, 162, 7, 39, 2, 2, 162, 40, 3, 2, 2, 2, 163, 164, 7, 45, 2, 2, 164, 42, 3, 2, 2, 2, 165, 166, 7, 47, 2, 2, 166, 44, 3, 2, 2, 2, 167, 168, 7, 63, 2, 2, 168, 46, 3, 2, 2, 2, 169, 170, 7, 35, 2, 2, 170, 171, 7, 63, 2, 2, 171, 48, 3, 2, 2, 2, 172, 173, 7, 64, 2, 2, 173, 50, 3, 2, 2, 2, 174, 175, 7, 64, 2, 2, 175, 176, 7, 63, 2, 2, 176, 52, 3, 2, 2, 2, 177, 178, 7, 62, 2, 2, 178, 54, 3, 2, 2, 2, 179, 180, 7, 62, 2, 2, 180, 181, 7, 64, 2, 2, 181, 56, 3, 2, 2, 2, 182, 183, 7, 62, 2, 2, 183, 184, 7, 63, 2, 2, 184, 58, 3, 2, 2, 2, 185, 186, 7, 78, 2, 2, 186, 187, 7, 75, 2, 2, 187, 188, 7, 77, 2, 2, 188, 189, 7, 71, 2, 2, 189, 60, 3, 2, 2, 2, 190, 191, 7, 71, 2, 2, 191, 192, 7, 90, 2, 2, 192, 193, 7, 75, 2, 2, 193, 194, 7, 85, 2, 2, 194, 195, 7, 86, 2, 2, 195, 196, 7, 85, 2, 2, 196, 62, 3, 2, 2, 2, 197, 198, 7, 75, 2, 2, 198, 199, 7, 80, 2, 2, 199, 64, 3, 2, 2, 2, 200, 201, 7, 86, 2, 2, 201, 202, 7, 84, 2, 2, 202, 203, 7, 87, 2, 2, 203, 204, 7, 71, 2, 2, 204, 66, 3, 2, 2, 2, 205, 206, 7, 72, 2, 2, 206, 207, 7, 67, 2, 2, 207, 208, 7, 78, 2, 2, 208, 209, 7, 85, 2, 2, 209, 210, 7, 71, 2, 2, 210, 68, 3, 2, 2, 2, 211, 212, 5, 7, 4, 2, 212, 70, 3, 2, 2, 2, 213, 214, 5, 9, 5, 2, 214, 72, 3, 2, 2, 2, 215, 217, 5, 11, 6, 2, 216, 215, 3, 2, 2, 2, 217, 218, 3, 2, 2, 2, 218, 216, 3, 2, 2, 2, 218, 219, 3, 2, 2, 2, 219, 74, 3, 2, 2, 2, 220, 222, 9, 9, 2, 2, 221, 220, 3, 2, 2, 2, 222, 223, 3, 2, 2, 2, 223, 221, 3, 2, 2, 2, 223, 224, 3, 2, 2, 2, 224, 76, 3, 2, 2, 2, 225, 227, 9, 3, 2, 2, 226, 225, 3, 2, 2, 2, 227, 228, 3, 2, 2, 2, 228, 226, 3, 2, 2, 2, 228, 229, 3, 2, 2, 2, 229, 78, 3, 2, 2, 2, 230, 234, 9, 7, 2, 2, 231, 233, 9, 8, 2, 2, 232, 231, 3, 2, 2, 2, 233, 236, 3, 2, 2, 2, 234, 232, 3, 2, 2, 2, 234, 235, 3, 2, 2, 2, 235, 80, 3, 2, 2, 2, 236, 234, 3, 2, 2, 2, 15, 2, 84, 91, 99, 101, 112, 114, 125, 140, 218, 223, 228, 234, 3, 8, 2, 2] \ No newline at end of file diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/CESQLParserLexer.tokens b/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/CESQLParserLexer.tokens new file mode 100644 index 000000000..913f0bc71 --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/CESQLParserLexer.tokens @@ -0,0 +1,59 @@ +SPACE=1 +LR_BRACKET=2 +RR_BRACKET=3 +COMMA=4 +SINGLE_QUOTE_SYMB=5 +DOUBLE_QUOTE_SYMB=6 +AND=7 +OR=8 +XOR=9 +NOT=10 +STAR=11 +DIVIDE=12 +MODULE=13 +PLUS=14 +MINUS=15 +EQUAL=16 +NOT_EQUAL=17 +GREATER=18 +GREATER_OR_EQUAL=19 +LESS=20 +LESS_GREATER=21 +LESS_OR_EQUAL=22 +LIKE=23 +EXISTS=24 +IN=25 +TRUE=26 +FALSE=27 +DQUOTED_STRING_LITERAL=28 +SQUOTED_STRING_LITERAL=29 +INTEGER_LITERAL=30 +IDENTIFIER=31 +IDENTIFIER_WITH_NUMBER=32 +FUNCTION_IDENTIFIER_WITH_UNDERSCORE=33 +'('=2 +')'=3 +','=4 +'\''=5 +'"'=6 +'AND'=7 +'OR'=8 +'XOR'=9 +'NOT'=10 +'*'=11 +'/'=12 +'%'=13 +'+'=14 +'-'=15 +'='=16 +'!='=17 +'>'=18 +'>='=19 +'<'=20 +'<>'=21 +'<='=22 +'LIKE'=23 +'EXISTS'=24 +'IN'=25 +'TRUE'=26 +'FALSE'=27 diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/cesqlparser_base_visitor.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/cesqlparser_base_visitor.go new file mode 100644 index 000000000..a7eb0e1f3 --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/cesqlparser_base_visitor.go @@ -0,0 +1,109 @@ +/* + Copyright 2021 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +// Code generated from CESQLParser.g4 by ANTLR 4.9. DO NOT EDIT. + +package gen // CESQLParser +import "github.com/antlr/antlr4/runtime/Go/antlr" + +type BaseCESQLParserVisitor struct { + *antlr.BaseParseTreeVisitor +} + +func (v *BaseCESQLParserVisitor) VisitCesql(ctx *CesqlContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitInExpression(ctx *InExpressionContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitBinaryComparisonExpression(ctx *BinaryComparisonExpressionContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitAtomExpression(ctx *AtomExpressionContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitExistsExpression(ctx *ExistsExpressionContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitBinaryLogicExpression(ctx *BinaryLogicExpressionContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitLikeExpression(ctx *LikeExpressionContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitFunctionInvocationExpression(ctx *FunctionInvocationExpressionContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitBinaryMultiplicativeExpression(ctx *BinaryMultiplicativeExpressionContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitUnaryLogicExpression(ctx *UnaryLogicExpressionContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitUnaryNumericExpression(ctx *UnaryNumericExpressionContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitSubExpression(ctx *SubExpressionContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitBinaryAdditiveExpression(ctx *BinaryAdditiveExpressionContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitBooleanAtom(ctx *BooleanAtomContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitIntegerAtom(ctx *IntegerAtomContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitStringAtom(ctx *StringAtomContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitIdentifierAtom(ctx *IdentifierAtomContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitIdentifier(ctx *IdentifierContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitFunctionIdentifier(ctx *FunctionIdentifierContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitBooleanLiteral(ctx *BooleanLiteralContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitStringLiteral(ctx *StringLiteralContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitIntegerLiteral(ctx *IntegerLiteralContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitFunctionParameterList(ctx *FunctionParameterListContext) interface{} { + return v.VisitChildren(ctx) +} + +func (v *BaseCESQLParserVisitor) VisitSetExpression(ctx *SetExpressionContext) interface{} { + return v.VisitChildren(ctx) +} diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/cesqlparser_lexer.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/cesqlparser_lexer.go new file mode 100644 index 000000000..b51903faa --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/cesqlparser_lexer.go @@ -0,0 +1,231 @@ +/* + Copyright 2021 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +// Code generated from CESQLParser.g4 by ANTLR 4.9. DO NOT EDIT. + +package gen + +import ( + "fmt" + "unicode" + + "github.com/antlr/antlr4/runtime/Go/antlr" +) + +// Suppress unused import error +var _ = fmt.Printf +var _ = unicode.IsLetter + +var serializedLexerAtn = []uint16{ + 3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 35, 237, + 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, + 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, + 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, + 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, + 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, + 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, + 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, + 39, 9, 39, 4, 40, 9, 40, 3, 2, 6, 2, 83, 10, 2, 13, 2, 14, 2, 84, 3, 2, + 3, 2, 3, 3, 6, 3, 90, 10, 3, 13, 3, 14, 3, 91, 3, 4, 3, 4, 3, 4, 3, 4, + 3, 4, 3, 4, 7, 4, 100, 10, 4, 12, 4, 14, 4, 103, 11, 4, 3, 4, 3, 4, 3, + 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 7, 5, 113, 10, 5, 12, 5, 14, 5, 116, 11, + 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 7, 7, 124, 10, 7, 12, 7, 14, 7, + 127, 11, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, + 3, 12, 3, 13, 3, 13, 5, 13, 141, 10, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, + 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, + 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, + 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 27, + 3, 27, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, + 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, + 3, 32, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 34, 3, + 34, 3, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 6, 37, 217, 10, 37, 13, 37, + 14, 37, 218, 3, 38, 6, 38, 222, 10, 38, 13, 38, 14, 38, 223, 3, 39, 6, + 39, 227, 10, 39, 13, 39, 14, 39, 228, 3, 40, 3, 40, 7, 40, 233, 10, 40, + 12, 40, 14, 40, 236, 11, 40, 2, 2, 41, 3, 3, 5, 2, 7, 2, 9, 2, 11, 2, 13, + 2, 15, 4, 17, 5, 19, 6, 21, 7, 23, 8, 25, 2, 27, 9, 29, 10, 31, 11, 33, + 12, 35, 13, 37, 14, 39, 15, 41, 16, 43, 17, 45, 18, 47, 19, 49, 20, 51, + 21, 53, 22, 55, 23, 57, 24, 59, 25, 61, 26, 63, 27, 65, 28, 67, 29, 69, + 30, 71, 31, 73, 32, 75, 33, 77, 34, 79, 35, 3, 2, 10, 5, 2, 11, 12, 15, + 15, 34, 34, 5, 2, 50, 59, 67, 92, 99, 124, 4, 2, 36, 36, 94, 94, 4, 2, + 41, 41, 94, 94, 3, 2, 50, 59, 3, 2, 67, 92, 4, 2, 67, 92, 97, 97, 4, 2, + 67, 92, 99, 124, 2, 244, 2, 3, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, + 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 27, + 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, + 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, + 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, + 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, + 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, + 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, + 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 3, + 82, 3, 2, 2, 2, 5, 89, 3, 2, 2, 2, 7, 93, 3, 2, 2, 2, 9, 106, 3, 2, 2, + 2, 11, 119, 3, 2, 2, 2, 13, 121, 3, 2, 2, 2, 15, 128, 3, 2, 2, 2, 17, 130, + 3, 2, 2, 2, 19, 132, 3, 2, 2, 2, 21, 134, 3, 2, 2, 2, 23, 136, 3, 2, 2, + 2, 25, 140, 3, 2, 2, 2, 27, 142, 3, 2, 2, 2, 29, 146, 3, 2, 2, 2, 31, 149, + 3, 2, 2, 2, 33, 153, 3, 2, 2, 2, 35, 157, 3, 2, 2, 2, 37, 159, 3, 2, 2, + 2, 39, 161, 3, 2, 2, 2, 41, 163, 3, 2, 2, 2, 43, 165, 3, 2, 2, 2, 45, 167, + 3, 2, 2, 2, 47, 169, 3, 2, 2, 2, 49, 172, 3, 2, 2, 2, 51, 174, 3, 2, 2, + 2, 53, 177, 3, 2, 2, 2, 55, 179, 3, 2, 2, 2, 57, 182, 3, 2, 2, 2, 59, 185, + 3, 2, 2, 2, 61, 190, 3, 2, 2, 2, 63, 197, 3, 2, 2, 2, 65, 200, 3, 2, 2, + 2, 67, 205, 3, 2, 2, 2, 69, 211, 3, 2, 2, 2, 71, 213, 3, 2, 2, 2, 73, 216, + 3, 2, 2, 2, 75, 221, 3, 2, 2, 2, 77, 226, 3, 2, 2, 2, 79, 230, 3, 2, 2, + 2, 81, 83, 9, 2, 2, 2, 82, 81, 3, 2, 2, 2, 83, 84, 3, 2, 2, 2, 84, 82, + 3, 2, 2, 2, 84, 85, 3, 2, 2, 2, 85, 86, 3, 2, 2, 2, 86, 87, 8, 2, 2, 2, + 87, 4, 3, 2, 2, 2, 88, 90, 9, 3, 2, 2, 89, 88, 3, 2, 2, 2, 90, 91, 3, 2, + 2, 2, 91, 89, 3, 2, 2, 2, 91, 92, 3, 2, 2, 2, 92, 6, 3, 2, 2, 2, 93, 101, + 7, 36, 2, 2, 94, 95, 7, 94, 2, 2, 95, 100, 11, 2, 2, 2, 96, 97, 7, 36, + 2, 2, 97, 100, 7, 36, 2, 2, 98, 100, 10, 4, 2, 2, 99, 94, 3, 2, 2, 2, 99, + 96, 3, 2, 2, 2, 99, 98, 3, 2, 2, 2, 100, 103, 3, 2, 2, 2, 101, 99, 3, 2, + 2, 2, 101, 102, 3, 2, 2, 2, 102, 104, 3, 2, 2, 2, 103, 101, 3, 2, 2, 2, + 104, 105, 7, 36, 2, 2, 105, 8, 3, 2, 2, 2, 106, 114, 7, 41, 2, 2, 107, + 108, 7, 94, 2, 2, 108, 113, 11, 2, 2, 2, 109, 110, 7, 41, 2, 2, 110, 113, + 7, 41, 2, 2, 111, 113, 10, 5, 2, 2, 112, 107, 3, 2, 2, 2, 112, 109, 3, + 2, 2, 2, 112, 111, 3, 2, 2, 2, 113, 116, 3, 2, 2, 2, 114, 112, 3, 2, 2, + 2, 114, 115, 3, 2, 2, 2, 115, 117, 3, 2, 2, 2, 116, 114, 3, 2, 2, 2, 117, + 118, 7, 41, 2, 2, 118, 10, 3, 2, 2, 2, 119, 120, 9, 6, 2, 2, 120, 12, 3, + 2, 2, 2, 121, 125, 9, 7, 2, 2, 122, 124, 9, 8, 2, 2, 123, 122, 3, 2, 2, + 2, 124, 127, 3, 2, 2, 2, 125, 123, 3, 2, 2, 2, 125, 126, 3, 2, 2, 2, 126, + 14, 3, 2, 2, 2, 127, 125, 3, 2, 2, 2, 128, 129, 7, 42, 2, 2, 129, 16, 3, + 2, 2, 2, 130, 131, 7, 43, 2, 2, 131, 18, 3, 2, 2, 2, 132, 133, 7, 46, 2, + 2, 133, 20, 3, 2, 2, 2, 134, 135, 7, 41, 2, 2, 135, 22, 3, 2, 2, 2, 136, + 137, 7, 36, 2, 2, 137, 24, 3, 2, 2, 2, 138, 141, 5, 21, 11, 2, 139, 141, + 5, 23, 12, 2, 140, 138, 3, 2, 2, 2, 140, 139, 3, 2, 2, 2, 141, 26, 3, 2, + 2, 2, 142, 143, 7, 67, 2, 2, 143, 144, 7, 80, 2, 2, 144, 145, 7, 70, 2, + 2, 145, 28, 3, 2, 2, 2, 146, 147, 7, 81, 2, 2, 147, 148, 7, 84, 2, 2, 148, + 30, 3, 2, 2, 2, 149, 150, 7, 90, 2, 2, 150, 151, 7, 81, 2, 2, 151, 152, + 7, 84, 2, 2, 152, 32, 3, 2, 2, 2, 153, 154, 7, 80, 2, 2, 154, 155, 7, 81, + 2, 2, 155, 156, 7, 86, 2, 2, 156, 34, 3, 2, 2, 2, 157, 158, 7, 44, 2, 2, + 158, 36, 3, 2, 2, 2, 159, 160, 7, 49, 2, 2, 160, 38, 3, 2, 2, 2, 161, 162, + 7, 39, 2, 2, 162, 40, 3, 2, 2, 2, 163, 164, 7, 45, 2, 2, 164, 42, 3, 2, + 2, 2, 165, 166, 7, 47, 2, 2, 166, 44, 3, 2, 2, 2, 167, 168, 7, 63, 2, 2, + 168, 46, 3, 2, 2, 2, 169, 170, 7, 35, 2, 2, 170, 171, 7, 63, 2, 2, 171, + 48, 3, 2, 2, 2, 172, 173, 7, 64, 2, 2, 173, 50, 3, 2, 2, 2, 174, 175, 7, + 64, 2, 2, 175, 176, 7, 63, 2, 2, 176, 52, 3, 2, 2, 2, 177, 178, 7, 62, + 2, 2, 178, 54, 3, 2, 2, 2, 179, 180, 7, 62, 2, 2, 180, 181, 7, 64, 2, 2, + 181, 56, 3, 2, 2, 2, 182, 183, 7, 62, 2, 2, 183, 184, 7, 63, 2, 2, 184, + 58, 3, 2, 2, 2, 185, 186, 7, 78, 2, 2, 186, 187, 7, 75, 2, 2, 187, 188, + 7, 77, 2, 2, 188, 189, 7, 71, 2, 2, 189, 60, 3, 2, 2, 2, 190, 191, 7, 71, + 2, 2, 191, 192, 7, 90, 2, 2, 192, 193, 7, 75, 2, 2, 193, 194, 7, 85, 2, + 2, 194, 195, 7, 86, 2, 2, 195, 196, 7, 85, 2, 2, 196, 62, 3, 2, 2, 2, 197, + 198, 7, 75, 2, 2, 198, 199, 7, 80, 2, 2, 199, 64, 3, 2, 2, 2, 200, 201, + 7, 86, 2, 2, 201, 202, 7, 84, 2, 2, 202, 203, 7, 87, 2, 2, 203, 204, 7, + 71, 2, 2, 204, 66, 3, 2, 2, 2, 205, 206, 7, 72, 2, 2, 206, 207, 7, 67, + 2, 2, 207, 208, 7, 78, 2, 2, 208, 209, 7, 85, 2, 2, 209, 210, 7, 71, 2, + 2, 210, 68, 3, 2, 2, 2, 211, 212, 5, 7, 4, 2, 212, 70, 3, 2, 2, 2, 213, + 214, 5, 9, 5, 2, 214, 72, 3, 2, 2, 2, 215, 217, 5, 11, 6, 2, 216, 215, + 3, 2, 2, 2, 217, 218, 3, 2, 2, 2, 218, 216, 3, 2, 2, 2, 218, 219, 3, 2, + 2, 2, 219, 74, 3, 2, 2, 2, 220, 222, 9, 9, 2, 2, 221, 220, 3, 2, 2, 2, + 222, 223, 3, 2, 2, 2, 223, 221, 3, 2, 2, 2, 223, 224, 3, 2, 2, 2, 224, + 76, 3, 2, 2, 2, 225, 227, 9, 3, 2, 2, 226, 225, 3, 2, 2, 2, 227, 228, 3, + 2, 2, 2, 228, 226, 3, 2, 2, 2, 228, 229, 3, 2, 2, 2, 229, 78, 3, 2, 2, + 2, 230, 234, 9, 7, 2, 2, 231, 233, 9, 8, 2, 2, 232, 231, 3, 2, 2, 2, 233, + 236, 3, 2, 2, 2, 234, 232, 3, 2, 2, 2, 234, 235, 3, 2, 2, 2, 235, 80, 3, + 2, 2, 2, 236, 234, 3, 2, 2, 2, 15, 2, 84, 91, 99, 101, 112, 114, 125, 140, + 218, 223, 228, 234, 3, 8, 2, 2, +} + +var lexerChannelNames = []string{ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN", +} + +var lexerModeNames = []string{ + "DEFAULT_MODE", +} + +var lexerLiteralNames = []string{ + "", "", "'('", "')'", "','", "'''", "'\"'", "'AND'", "'OR'", "'XOR'", "'NOT'", + "'*'", "'/'", "'%'", "'+'", "'-'", "'='", "'!='", "'>'", "'>='", "'<'", + "'<>'", "'<='", "'LIKE'", "'EXISTS'", "'IN'", "'TRUE'", "'FALSE'", +} + +var lexerSymbolicNames = []string{ + "", "SPACE", "LR_BRACKET", "RR_BRACKET", "COMMA", "SINGLE_QUOTE_SYMB", + "DOUBLE_QUOTE_SYMB", "AND", "OR", "XOR", "NOT", "STAR", "DIVIDE", "MODULE", + "PLUS", "MINUS", "EQUAL", "NOT_EQUAL", "GREATER", "GREATER_OR_EQUAL", "LESS", + "LESS_GREATER", "LESS_OR_EQUAL", "LIKE", "EXISTS", "IN", "TRUE", "FALSE", + "DQUOTED_STRING_LITERAL", "SQUOTED_STRING_LITERAL", "INTEGER_LITERAL", + "IDENTIFIER", "IDENTIFIER_WITH_NUMBER", "FUNCTION_IDENTIFIER_WITH_UNDERSCORE", +} + +var lexerRuleNames = []string{ + "SPACE", "ID_LITERAL", "DQUOTA_STRING", "SQUOTA_STRING", "INT_DIGIT", "FN_LITERAL", + "LR_BRACKET", "RR_BRACKET", "COMMA", "SINGLE_QUOTE_SYMB", "DOUBLE_QUOTE_SYMB", + "QUOTE_SYMB", "AND", "OR", "XOR", "NOT", "STAR", "DIVIDE", "MODULE", "PLUS", + "MINUS", "EQUAL", "NOT_EQUAL", "GREATER", "GREATER_OR_EQUAL", "LESS", "LESS_GREATER", + "LESS_OR_EQUAL", "LIKE", "EXISTS", "IN", "TRUE", "FALSE", "DQUOTED_STRING_LITERAL", + "SQUOTED_STRING_LITERAL", "INTEGER_LITERAL", "IDENTIFIER", "IDENTIFIER_WITH_NUMBER", + "FUNCTION_IDENTIFIER_WITH_UNDERSCORE", +} + +type CESQLParserLexer struct { + *antlr.BaseLexer + channelNames []string + modeNames []string + // TODO: EOF string +} + +// NewCESQLParserLexer produces a new lexer instance for the optional input antlr.CharStream. +// +// The *CESQLParserLexer instance produced may be reused by calling the SetInputStream method. +// The initial lexer configuration is expensive to construct, and the object is not thread-safe; +// however, if used within a Golang sync.Pool, the construction cost amortizes well and the +// objects can be used in a thread-safe manner. +func NewCESQLParserLexer(input antlr.CharStream) *CESQLParserLexer { + l := new(CESQLParserLexer) + lexerDeserializer := antlr.NewATNDeserializer(nil) + lexerAtn := lexerDeserializer.DeserializeFromUInt16(serializedLexerAtn) + lexerDecisionToDFA := make([]*antlr.DFA, len(lexerAtn.DecisionToState)) + for index, ds := range lexerAtn.DecisionToState { + lexerDecisionToDFA[index] = antlr.NewDFA(ds, index) + } + l.BaseLexer = antlr.NewBaseLexer(input) + l.Interpreter = antlr.NewLexerATNSimulator(l, lexerAtn, lexerDecisionToDFA, antlr.NewPredictionContextCache()) + + l.channelNames = lexerChannelNames + l.modeNames = lexerModeNames + l.RuleNames = lexerRuleNames + l.LiteralNames = lexerLiteralNames + l.SymbolicNames = lexerSymbolicNames + l.GrammarFileName = "CESQLParser.g4" + // TODO: l.EOF = antlr.TokenEOF + + return l +} + +// CESQLParserLexer tokens. +const ( + CESQLParserLexerSPACE = 1 + CESQLParserLexerLR_BRACKET = 2 + CESQLParserLexerRR_BRACKET = 3 + CESQLParserLexerCOMMA = 4 + CESQLParserLexerSINGLE_QUOTE_SYMB = 5 + CESQLParserLexerDOUBLE_QUOTE_SYMB = 6 + CESQLParserLexerAND = 7 + CESQLParserLexerOR = 8 + CESQLParserLexerXOR = 9 + CESQLParserLexerNOT = 10 + CESQLParserLexerSTAR = 11 + CESQLParserLexerDIVIDE = 12 + CESQLParserLexerMODULE = 13 + CESQLParserLexerPLUS = 14 + CESQLParserLexerMINUS = 15 + CESQLParserLexerEQUAL = 16 + CESQLParserLexerNOT_EQUAL = 17 + CESQLParserLexerGREATER = 18 + CESQLParserLexerGREATER_OR_EQUAL = 19 + CESQLParserLexerLESS = 20 + CESQLParserLexerLESS_GREATER = 21 + CESQLParserLexerLESS_OR_EQUAL = 22 + CESQLParserLexerLIKE = 23 + CESQLParserLexerEXISTS = 24 + CESQLParserLexerIN = 25 + CESQLParserLexerTRUE = 26 + CESQLParserLexerFALSE = 27 + CESQLParserLexerDQUOTED_STRING_LITERAL = 28 + CESQLParserLexerSQUOTED_STRING_LITERAL = 29 + CESQLParserLexerINTEGER_LITERAL = 30 + CESQLParserLexerIDENTIFIER = 31 + CESQLParserLexerIDENTIFIER_WITH_NUMBER = 32 + CESQLParserLexerFUNCTION_IDENTIFIER_WITH_UNDERSCORE = 33 +) diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/cesqlparser_parser.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/cesqlparser_parser.go new file mode 100644 index 000000000..71d9837ee --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/cesqlparser_parser.go @@ -0,0 +1,2356 @@ +/* + Copyright 2021 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +// Code generated from CESQLParser.g4 by ANTLR 4.9. DO NOT EDIT. + +package gen // CESQLParser +import ( + "fmt" + "reflect" + "strconv" + + "github.com/antlr/antlr4/runtime/Go/antlr" +) + +// Suppress unused import errors +var _ = fmt.Printf +var _ = reflect.Copy +var _ = strconv.Itoa + +var parserATN = []uint16{ + 3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 35, 112, + 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, + 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 3, 2, 3, 2, 3, 2, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 5, 3, 41, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 57, 10, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 5, 3, 63, 10, 3, 3, 3, 3, 3, 7, 3, 67, 10, 3, 12, 3, 14, + 3, 70, 11, 3, 3, 4, 3, 4, 3, 4, 3, 4, 5, 4, 76, 10, 4, 3, 5, 3, 5, 3, 6, + 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 7, + 10, 92, 10, 10, 12, 10, 14, 10, 95, 11, 10, 5, 10, 97, 10, 10, 3, 10, 3, + 10, 3, 11, 3, 11, 3, 11, 3, 11, 7, 11, 105, 10, 11, 12, 11, 14, 11, 108, + 11, 11, 3, 11, 3, 11, 3, 11, 2, 3, 4, 12, 2, 4, 6, 8, 10, 12, 14, 16, 18, + 20, 2, 10, 3, 2, 13, 15, 3, 2, 16, 17, 3, 2, 18, 24, 3, 2, 9, 11, 3, 2, + 33, 34, 4, 2, 33, 33, 35, 35, 3, 2, 28, 29, 3, 2, 30, 31, 2, 120, 2, 22, + 3, 2, 2, 2, 4, 40, 3, 2, 2, 2, 6, 75, 3, 2, 2, 2, 8, 77, 3, 2, 2, 2, 10, + 79, 3, 2, 2, 2, 12, 81, 3, 2, 2, 2, 14, 83, 3, 2, 2, 2, 16, 85, 3, 2, 2, + 2, 18, 87, 3, 2, 2, 2, 20, 100, 3, 2, 2, 2, 22, 23, 5, 4, 3, 2, 23, 24, + 7, 2, 2, 3, 24, 3, 3, 2, 2, 2, 25, 26, 8, 3, 1, 2, 26, 27, 5, 10, 6, 2, + 27, 28, 5, 18, 10, 2, 28, 41, 3, 2, 2, 2, 29, 30, 7, 12, 2, 2, 30, 41, + 5, 4, 3, 13, 31, 32, 7, 17, 2, 2, 32, 41, 5, 4, 3, 12, 33, 34, 7, 26, 2, + 2, 34, 41, 5, 8, 5, 2, 35, 36, 7, 4, 2, 2, 36, 37, 5, 4, 3, 2, 37, 38, + 7, 5, 2, 2, 38, 41, 3, 2, 2, 2, 39, 41, 5, 6, 4, 2, 40, 25, 3, 2, 2, 2, + 40, 29, 3, 2, 2, 2, 40, 31, 3, 2, 2, 2, 40, 33, 3, 2, 2, 2, 40, 35, 3, + 2, 2, 2, 40, 39, 3, 2, 2, 2, 41, 68, 3, 2, 2, 2, 42, 43, 12, 8, 2, 2, 43, + 44, 9, 2, 2, 2, 44, 67, 5, 4, 3, 9, 45, 46, 12, 7, 2, 2, 46, 47, 9, 3, + 2, 2, 47, 67, 5, 4, 3, 8, 48, 49, 12, 6, 2, 2, 49, 50, 9, 4, 2, 2, 50, + 67, 5, 4, 3, 7, 51, 52, 12, 5, 2, 2, 52, 53, 9, 5, 2, 2, 53, 67, 5, 4, + 3, 5, 54, 56, 12, 11, 2, 2, 55, 57, 7, 12, 2, 2, 56, 55, 3, 2, 2, 2, 56, + 57, 3, 2, 2, 2, 57, 58, 3, 2, 2, 2, 58, 59, 7, 25, 2, 2, 59, 67, 5, 14, + 8, 2, 60, 62, 12, 9, 2, 2, 61, 63, 7, 12, 2, 2, 62, 61, 3, 2, 2, 2, 62, + 63, 3, 2, 2, 2, 63, 64, 3, 2, 2, 2, 64, 65, 7, 27, 2, 2, 65, 67, 5, 20, + 11, 2, 66, 42, 3, 2, 2, 2, 66, 45, 3, 2, 2, 2, 66, 48, 3, 2, 2, 2, 66, + 51, 3, 2, 2, 2, 66, 54, 3, 2, 2, 2, 66, 60, 3, 2, 2, 2, 67, 70, 3, 2, 2, + 2, 68, 66, 3, 2, 2, 2, 68, 69, 3, 2, 2, 2, 69, 5, 3, 2, 2, 2, 70, 68, 3, + 2, 2, 2, 71, 76, 5, 12, 7, 2, 72, 76, 5, 16, 9, 2, 73, 76, 5, 14, 8, 2, + 74, 76, 5, 8, 5, 2, 75, 71, 3, 2, 2, 2, 75, 72, 3, 2, 2, 2, 75, 73, 3, + 2, 2, 2, 75, 74, 3, 2, 2, 2, 76, 7, 3, 2, 2, 2, 77, 78, 9, 6, 2, 2, 78, + 9, 3, 2, 2, 2, 79, 80, 9, 7, 2, 2, 80, 11, 3, 2, 2, 2, 81, 82, 9, 8, 2, + 2, 82, 13, 3, 2, 2, 2, 83, 84, 9, 9, 2, 2, 84, 15, 3, 2, 2, 2, 85, 86, + 7, 32, 2, 2, 86, 17, 3, 2, 2, 2, 87, 96, 7, 4, 2, 2, 88, 93, 5, 4, 3, 2, + 89, 90, 7, 6, 2, 2, 90, 92, 5, 4, 3, 2, 91, 89, 3, 2, 2, 2, 92, 95, 3, + 2, 2, 2, 93, 91, 3, 2, 2, 2, 93, 94, 3, 2, 2, 2, 94, 97, 3, 2, 2, 2, 95, + 93, 3, 2, 2, 2, 96, 88, 3, 2, 2, 2, 96, 97, 3, 2, 2, 2, 97, 98, 3, 2, 2, + 2, 98, 99, 7, 5, 2, 2, 99, 19, 3, 2, 2, 2, 100, 101, 7, 4, 2, 2, 101, 106, + 5, 4, 3, 2, 102, 103, 7, 6, 2, 2, 103, 105, 5, 4, 3, 2, 104, 102, 3, 2, + 2, 2, 105, 108, 3, 2, 2, 2, 106, 104, 3, 2, 2, 2, 106, 107, 3, 2, 2, 2, + 107, 109, 3, 2, 2, 2, 108, 106, 3, 2, 2, 2, 109, 110, 7, 5, 2, 2, 110, + 21, 3, 2, 2, 2, 11, 40, 56, 62, 66, 68, 75, 93, 96, 106, +} +var literalNames = []string{ + "", "", "'('", "')'", "','", "'''", "'\"'", "'AND'", "'OR'", "'XOR'", "'NOT'", + "'*'", "'/'", "'%'", "'+'", "'-'", "'='", "'!='", "'>'", "'>='", "'<'", + "'<>'", "'<='", "'LIKE'", "'EXISTS'", "'IN'", "'TRUE'", "'FALSE'", +} +var symbolicNames = []string{ + "", "SPACE", "LR_BRACKET", "RR_BRACKET", "COMMA", "SINGLE_QUOTE_SYMB", + "DOUBLE_QUOTE_SYMB", "AND", "OR", "XOR", "NOT", "STAR", "DIVIDE", "MODULE", + "PLUS", "MINUS", "EQUAL", "NOT_EQUAL", "GREATER", "GREATER_OR_EQUAL", "LESS", + "LESS_GREATER", "LESS_OR_EQUAL", "LIKE", "EXISTS", "IN", "TRUE", "FALSE", + "DQUOTED_STRING_LITERAL", "SQUOTED_STRING_LITERAL", "INTEGER_LITERAL", + "IDENTIFIER", "IDENTIFIER_WITH_NUMBER", "FUNCTION_IDENTIFIER_WITH_UNDERSCORE", +} + +var ruleNames = []string{ + "cesql", "expression", "atom", "identifier", "functionIdentifier", "booleanLiteral", + "stringLiteral", "integerLiteral", "functionParameterList", "setExpression", +} + +type CESQLParserParser struct { + *antlr.BaseParser +} + +// NewCESQLParserParser produces a new parser instance for the optional input antlr.TokenStream. +// +// The *CESQLParserParser instance produced may be reused by calling the SetInputStream method. +// The initial parser configuration is expensive to construct, and the object is not thread-safe; +// however, if used within a Golang sync.Pool, the construction cost amortizes well and the +// objects can be used in a thread-safe manner. +func NewCESQLParserParser(input antlr.TokenStream) *CESQLParserParser { + this := new(CESQLParserParser) + deserializer := antlr.NewATNDeserializer(nil) + deserializedATN := deserializer.DeserializeFromUInt16(parserATN) + decisionToDFA := make([]*antlr.DFA, len(deserializedATN.DecisionToState)) + for index, ds := range deserializedATN.DecisionToState { + decisionToDFA[index] = antlr.NewDFA(ds, index) + } + this.BaseParser = antlr.NewBaseParser(input) + + this.Interpreter = antlr.NewParserATNSimulator(this, deserializedATN, decisionToDFA, antlr.NewPredictionContextCache()) + this.RuleNames = ruleNames + this.LiteralNames = literalNames + this.SymbolicNames = symbolicNames + this.GrammarFileName = "CESQLParser.g4" + + return this +} + +// CESQLParserParser tokens. +const ( + CESQLParserParserEOF = antlr.TokenEOF + CESQLParserParserSPACE = 1 + CESQLParserParserLR_BRACKET = 2 + CESQLParserParserRR_BRACKET = 3 + CESQLParserParserCOMMA = 4 + CESQLParserParserSINGLE_QUOTE_SYMB = 5 + CESQLParserParserDOUBLE_QUOTE_SYMB = 6 + CESQLParserParserAND = 7 + CESQLParserParserOR = 8 + CESQLParserParserXOR = 9 + CESQLParserParserNOT = 10 + CESQLParserParserSTAR = 11 + CESQLParserParserDIVIDE = 12 + CESQLParserParserMODULE = 13 + CESQLParserParserPLUS = 14 + CESQLParserParserMINUS = 15 + CESQLParserParserEQUAL = 16 + CESQLParserParserNOT_EQUAL = 17 + CESQLParserParserGREATER = 18 + CESQLParserParserGREATER_OR_EQUAL = 19 + CESQLParserParserLESS = 20 + CESQLParserParserLESS_GREATER = 21 + CESQLParserParserLESS_OR_EQUAL = 22 + CESQLParserParserLIKE = 23 + CESQLParserParserEXISTS = 24 + CESQLParserParserIN = 25 + CESQLParserParserTRUE = 26 + CESQLParserParserFALSE = 27 + CESQLParserParserDQUOTED_STRING_LITERAL = 28 + CESQLParserParserSQUOTED_STRING_LITERAL = 29 + CESQLParserParserINTEGER_LITERAL = 30 + CESQLParserParserIDENTIFIER = 31 + CESQLParserParserIDENTIFIER_WITH_NUMBER = 32 + CESQLParserParserFUNCTION_IDENTIFIER_WITH_UNDERSCORE = 33 +) + +// CESQLParserParser rules. +const ( + CESQLParserParserRULE_cesql = 0 + CESQLParserParserRULE_expression = 1 + CESQLParserParserRULE_atom = 2 + CESQLParserParserRULE_identifier = 3 + CESQLParserParserRULE_functionIdentifier = 4 + CESQLParserParserRULE_booleanLiteral = 5 + CESQLParserParserRULE_stringLiteral = 6 + CESQLParserParserRULE_integerLiteral = 7 + CESQLParserParserRULE_functionParameterList = 8 + CESQLParserParserRULE_setExpression = 9 +) + +// ICesqlContext is an interface to support dynamic dispatch. +type ICesqlContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // IsCesqlContext differentiates from other interfaces. + IsCesqlContext() +} + +type CesqlContext struct { + *antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyCesqlContext() *CesqlContext { + var p = new(CesqlContext) + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(nil, -1) + p.RuleIndex = CESQLParserParserRULE_cesql + return p +} + +func (*CesqlContext) IsCesqlContext() {} + +func NewCesqlContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *CesqlContext { + var p = new(CesqlContext) + + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(parent, invokingState) + + p.parser = parser + p.RuleIndex = CESQLParserParserRULE_cesql + + return p +} + +func (s *CesqlContext) GetParser() antlr.Parser { return s.parser } + +func (s *CesqlContext) Expression() IExpressionContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IExpressionContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IExpressionContext) +} + +func (s *CesqlContext) EOF() antlr.TerminalNode { + return s.GetToken(CESQLParserParserEOF, 0) +} + +func (s *CesqlContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *CesqlContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *CesqlContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case CESQLParserVisitor: + return t.VisitCesql(s) + + default: + return t.VisitChildren(s) + } +} + +func (p *CESQLParserParser) Cesql() (localctx ICesqlContext) { + localctx = NewCesqlContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 0, CESQLParserParserRULE_cesql) + + defer func() { + p.ExitRule() + }() + + defer func() { + if err := recover(); err != nil { + if v, ok := err.(antlr.RecognitionException); ok { + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + } else { + panic(err) + } + } + }() + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(20) + p.expression(0) + } + { + p.SetState(21) + p.Match(CESQLParserParserEOF) + } + + return localctx +} + +// IExpressionContext is an interface to support dynamic dispatch. +type IExpressionContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // IsExpressionContext differentiates from other interfaces. + IsExpressionContext() +} + +type ExpressionContext struct { + *antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyExpressionContext() *ExpressionContext { + var p = new(ExpressionContext) + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(nil, -1) + p.RuleIndex = CESQLParserParserRULE_expression + return p +} + +func (*ExpressionContext) IsExpressionContext() {} + +func NewExpressionContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *ExpressionContext { + var p = new(ExpressionContext) + + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(parent, invokingState) + + p.parser = parser + p.RuleIndex = CESQLParserParserRULE_expression + + return p +} + +func (s *ExpressionContext) GetParser() antlr.Parser { return s.parser } + +func (s *ExpressionContext) CopyFrom(ctx *ExpressionContext) { + s.BaseParserRuleContext.CopyFrom(ctx.BaseParserRuleContext) +} + +func (s *ExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ExpressionContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +type InExpressionContext struct { + *ExpressionContext +} + +func NewInExpressionContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *InExpressionContext { + var p = new(InExpressionContext) + + p.ExpressionContext = NewEmptyExpressionContext() + p.parser = parser + p.CopyFrom(ctx.(*ExpressionContext)) + + return p +} + +func (s *InExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *InExpressionContext) Expression() IExpressionContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IExpressionContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IExpressionContext) +} + +func (s *InExpressionContext) IN() antlr.TerminalNode { + return s.GetToken(CESQLParserParserIN, 0) +} + +func (s *InExpressionContext) SetExpression() ISetExpressionContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*ISetExpressionContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(ISetExpressionContext) +} + +func (s *InExpressionContext) NOT() antlr.TerminalNode { + return s.GetToken(CESQLParserParserNOT, 0) +} + +func (s *InExpressionContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case CESQLParserVisitor: + return t.VisitInExpression(s) + + default: + return t.VisitChildren(s) + } +} + +type BinaryComparisonExpressionContext struct { + *ExpressionContext +} + +func NewBinaryComparisonExpressionContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *BinaryComparisonExpressionContext { + var p = new(BinaryComparisonExpressionContext) + + p.ExpressionContext = NewEmptyExpressionContext() + p.parser = parser + p.CopyFrom(ctx.(*ExpressionContext)) + + return p +} + +func (s *BinaryComparisonExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *BinaryComparisonExpressionContext) AllExpression() []IExpressionContext { + var ts = s.GetTypedRuleContexts(reflect.TypeOf((*IExpressionContext)(nil)).Elem()) + var tst = make([]IExpressionContext, len(ts)) + + for i, t := range ts { + if t != nil { + tst[i] = t.(IExpressionContext) + } + } + + return tst +} + +func (s *BinaryComparisonExpressionContext) Expression(i int) IExpressionContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IExpressionContext)(nil)).Elem(), i) + + if t == nil { + return nil + } + + return t.(IExpressionContext) +} + +func (s *BinaryComparisonExpressionContext) EQUAL() antlr.TerminalNode { + return s.GetToken(CESQLParserParserEQUAL, 0) +} + +func (s *BinaryComparisonExpressionContext) NOT_EQUAL() antlr.TerminalNode { + return s.GetToken(CESQLParserParserNOT_EQUAL, 0) +} + +func (s *BinaryComparisonExpressionContext) LESS_GREATER() antlr.TerminalNode { + return s.GetToken(CESQLParserParserLESS_GREATER, 0) +} + +func (s *BinaryComparisonExpressionContext) GREATER_OR_EQUAL() antlr.TerminalNode { + return s.GetToken(CESQLParserParserGREATER_OR_EQUAL, 0) +} + +func (s *BinaryComparisonExpressionContext) LESS_OR_EQUAL() antlr.TerminalNode { + return s.GetToken(CESQLParserParserLESS_OR_EQUAL, 0) +} + +func (s *BinaryComparisonExpressionContext) LESS() antlr.TerminalNode { + return s.GetToken(CESQLParserParserLESS, 0) +} + +func (s *BinaryComparisonExpressionContext) GREATER() antlr.TerminalNode { + return s.GetToken(CESQLParserParserGREATER, 0) +} + +func (s *BinaryComparisonExpressionContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case CESQLParserVisitor: + return t.VisitBinaryComparisonExpression(s) + + default: + return t.VisitChildren(s) + } +} + +type AtomExpressionContext struct { + *ExpressionContext +} + +func NewAtomExpressionContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *AtomExpressionContext { + var p = new(AtomExpressionContext) + + p.ExpressionContext = NewEmptyExpressionContext() + p.parser = parser + p.CopyFrom(ctx.(*ExpressionContext)) + + return p +} + +func (s *AtomExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *AtomExpressionContext) Atom() IAtomContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IAtomContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IAtomContext) +} + +func (s *AtomExpressionContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case CESQLParserVisitor: + return t.VisitAtomExpression(s) + + default: + return t.VisitChildren(s) + } +} + +type ExistsExpressionContext struct { + *ExpressionContext +} + +func NewExistsExpressionContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *ExistsExpressionContext { + var p = new(ExistsExpressionContext) + + p.ExpressionContext = NewEmptyExpressionContext() + p.parser = parser + p.CopyFrom(ctx.(*ExpressionContext)) + + return p +} + +func (s *ExistsExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ExistsExpressionContext) EXISTS() antlr.TerminalNode { + return s.GetToken(CESQLParserParserEXISTS, 0) +} + +func (s *ExistsExpressionContext) Identifier() IIdentifierContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IIdentifierContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IIdentifierContext) +} + +func (s *ExistsExpressionContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case CESQLParserVisitor: + return t.VisitExistsExpression(s) + + default: + return t.VisitChildren(s) + } +} + +type BinaryLogicExpressionContext struct { + *ExpressionContext +} + +func NewBinaryLogicExpressionContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *BinaryLogicExpressionContext { + var p = new(BinaryLogicExpressionContext) + + p.ExpressionContext = NewEmptyExpressionContext() + p.parser = parser + p.CopyFrom(ctx.(*ExpressionContext)) + + return p +} + +func (s *BinaryLogicExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *BinaryLogicExpressionContext) AllExpression() []IExpressionContext { + var ts = s.GetTypedRuleContexts(reflect.TypeOf((*IExpressionContext)(nil)).Elem()) + var tst = make([]IExpressionContext, len(ts)) + + for i, t := range ts { + if t != nil { + tst[i] = t.(IExpressionContext) + } + } + + return tst +} + +func (s *BinaryLogicExpressionContext) Expression(i int) IExpressionContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IExpressionContext)(nil)).Elem(), i) + + if t == nil { + return nil + } + + return t.(IExpressionContext) +} + +func (s *BinaryLogicExpressionContext) AND() antlr.TerminalNode { + return s.GetToken(CESQLParserParserAND, 0) +} + +func (s *BinaryLogicExpressionContext) OR() antlr.TerminalNode { + return s.GetToken(CESQLParserParserOR, 0) +} + +func (s *BinaryLogicExpressionContext) XOR() antlr.TerminalNode { + return s.GetToken(CESQLParserParserXOR, 0) +} + +func (s *BinaryLogicExpressionContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case CESQLParserVisitor: + return t.VisitBinaryLogicExpression(s) + + default: + return t.VisitChildren(s) + } +} + +type LikeExpressionContext struct { + *ExpressionContext +} + +func NewLikeExpressionContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *LikeExpressionContext { + var p = new(LikeExpressionContext) + + p.ExpressionContext = NewEmptyExpressionContext() + p.parser = parser + p.CopyFrom(ctx.(*ExpressionContext)) + + return p +} + +func (s *LikeExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *LikeExpressionContext) Expression() IExpressionContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IExpressionContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IExpressionContext) +} + +func (s *LikeExpressionContext) LIKE() antlr.TerminalNode { + return s.GetToken(CESQLParserParserLIKE, 0) +} + +func (s *LikeExpressionContext) StringLiteral() IStringLiteralContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IStringLiteralContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IStringLiteralContext) +} + +func (s *LikeExpressionContext) NOT() antlr.TerminalNode { + return s.GetToken(CESQLParserParserNOT, 0) +} + +func (s *LikeExpressionContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case CESQLParserVisitor: + return t.VisitLikeExpression(s) + + default: + return t.VisitChildren(s) + } +} + +type FunctionInvocationExpressionContext struct { + *ExpressionContext +} + +func NewFunctionInvocationExpressionContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *FunctionInvocationExpressionContext { + var p = new(FunctionInvocationExpressionContext) + + p.ExpressionContext = NewEmptyExpressionContext() + p.parser = parser + p.CopyFrom(ctx.(*ExpressionContext)) + + return p +} + +func (s *FunctionInvocationExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *FunctionInvocationExpressionContext) FunctionIdentifier() IFunctionIdentifierContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IFunctionIdentifierContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IFunctionIdentifierContext) +} + +func (s *FunctionInvocationExpressionContext) FunctionParameterList() IFunctionParameterListContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IFunctionParameterListContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IFunctionParameterListContext) +} + +func (s *FunctionInvocationExpressionContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case CESQLParserVisitor: + return t.VisitFunctionInvocationExpression(s) + + default: + return t.VisitChildren(s) + } +} + +type BinaryMultiplicativeExpressionContext struct { + *ExpressionContext +} + +func NewBinaryMultiplicativeExpressionContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *BinaryMultiplicativeExpressionContext { + var p = new(BinaryMultiplicativeExpressionContext) + + p.ExpressionContext = NewEmptyExpressionContext() + p.parser = parser + p.CopyFrom(ctx.(*ExpressionContext)) + + return p +} + +func (s *BinaryMultiplicativeExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *BinaryMultiplicativeExpressionContext) AllExpression() []IExpressionContext { + var ts = s.GetTypedRuleContexts(reflect.TypeOf((*IExpressionContext)(nil)).Elem()) + var tst = make([]IExpressionContext, len(ts)) + + for i, t := range ts { + if t != nil { + tst[i] = t.(IExpressionContext) + } + } + + return tst +} + +func (s *BinaryMultiplicativeExpressionContext) Expression(i int) IExpressionContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IExpressionContext)(nil)).Elem(), i) + + if t == nil { + return nil + } + + return t.(IExpressionContext) +} + +func (s *BinaryMultiplicativeExpressionContext) STAR() antlr.TerminalNode { + return s.GetToken(CESQLParserParserSTAR, 0) +} + +func (s *BinaryMultiplicativeExpressionContext) DIVIDE() antlr.TerminalNode { + return s.GetToken(CESQLParserParserDIVIDE, 0) +} + +func (s *BinaryMultiplicativeExpressionContext) MODULE() antlr.TerminalNode { + return s.GetToken(CESQLParserParserMODULE, 0) +} + +func (s *BinaryMultiplicativeExpressionContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case CESQLParserVisitor: + return t.VisitBinaryMultiplicativeExpression(s) + + default: + return t.VisitChildren(s) + } +} + +type UnaryLogicExpressionContext struct { + *ExpressionContext +} + +func NewUnaryLogicExpressionContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *UnaryLogicExpressionContext { + var p = new(UnaryLogicExpressionContext) + + p.ExpressionContext = NewEmptyExpressionContext() + p.parser = parser + p.CopyFrom(ctx.(*ExpressionContext)) + + return p +} + +func (s *UnaryLogicExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *UnaryLogicExpressionContext) NOT() antlr.TerminalNode { + return s.GetToken(CESQLParserParserNOT, 0) +} + +func (s *UnaryLogicExpressionContext) Expression() IExpressionContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IExpressionContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IExpressionContext) +} + +func (s *UnaryLogicExpressionContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case CESQLParserVisitor: + return t.VisitUnaryLogicExpression(s) + + default: + return t.VisitChildren(s) + } +} + +type UnaryNumericExpressionContext struct { + *ExpressionContext +} + +func NewUnaryNumericExpressionContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *UnaryNumericExpressionContext { + var p = new(UnaryNumericExpressionContext) + + p.ExpressionContext = NewEmptyExpressionContext() + p.parser = parser + p.CopyFrom(ctx.(*ExpressionContext)) + + return p +} + +func (s *UnaryNumericExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *UnaryNumericExpressionContext) MINUS() antlr.TerminalNode { + return s.GetToken(CESQLParserParserMINUS, 0) +} + +func (s *UnaryNumericExpressionContext) Expression() IExpressionContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IExpressionContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IExpressionContext) +} + +func (s *UnaryNumericExpressionContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case CESQLParserVisitor: + return t.VisitUnaryNumericExpression(s) + + default: + return t.VisitChildren(s) + } +} + +type SubExpressionContext struct { + *ExpressionContext +} + +func NewSubExpressionContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *SubExpressionContext { + var p = new(SubExpressionContext) + + p.ExpressionContext = NewEmptyExpressionContext() + p.parser = parser + p.CopyFrom(ctx.(*ExpressionContext)) + + return p +} + +func (s *SubExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *SubExpressionContext) LR_BRACKET() antlr.TerminalNode { + return s.GetToken(CESQLParserParserLR_BRACKET, 0) +} + +func (s *SubExpressionContext) Expression() IExpressionContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IExpressionContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IExpressionContext) +} + +func (s *SubExpressionContext) RR_BRACKET() antlr.TerminalNode { + return s.GetToken(CESQLParserParserRR_BRACKET, 0) +} + +func (s *SubExpressionContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case CESQLParserVisitor: + return t.VisitSubExpression(s) + + default: + return t.VisitChildren(s) + } +} + +type BinaryAdditiveExpressionContext struct { + *ExpressionContext +} + +func NewBinaryAdditiveExpressionContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *BinaryAdditiveExpressionContext { + var p = new(BinaryAdditiveExpressionContext) + + p.ExpressionContext = NewEmptyExpressionContext() + p.parser = parser + p.CopyFrom(ctx.(*ExpressionContext)) + + return p +} + +func (s *BinaryAdditiveExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *BinaryAdditiveExpressionContext) AllExpression() []IExpressionContext { + var ts = s.GetTypedRuleContexts(reflect.TypeOf((*IExpressionContext)(nil)).Elem()) + var tst = make([]IExpressionContext, len(ts)) + + for i, t := range ts { + if t != nil { + tst[i] = t.(IExpressionContext) + } + } + + return tst +} + +func (s *BinaryAdditiveExpressionContext) Expression(i int) IExpressionContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IExpressionContext)(nil)).Elem(), i) + + if t == nil { + return nil + } + + return t.(IExpressionContext) +} + +func (s *BinaryAdditiveExpressionContext) PLUS() antlr.TerminalNode { + return s.GetToken(CESQLParserParserPLUS, 0) +} + +func (s *BinaryAdditiveExpressionContext) MINUS() antlr.TerminalNode { + return s.GetToken(CESQLParserParserMINUS, 0) +} + +func (s *BinaryAdditiveExpressionContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { + switch t := visitor.(type) { + case CESQLParserVisitor: + return t.VisitBinaryAdditiveExpression(s) + + default: + return t.VisitChildren(s) + } +} + +func (p *CESQLParserParser) Expression() (localctx IExpressionContext) { + return p.expression(0) +} + +func (p *CESQLParserParser) expression(_p int) (localctx IExpressionContext) { + var _parentctx antlr.ParserRuleContext = p.GetParserRuleContext() + _parentState := p.GetState() + localctx = NewExpressionContext(p, p.GetParserRuleContext(), _parentState) + var _prevctx IExpressionContext = localctx + var _ antlr.ParserRuleContext = _prevctx // TODO: To prevent unused variable warning. + _startState := 2 + p.EnterRecursionRule(localctx, 2, CESQLParserParserRULE_expression, _p) + var _la int + + defer func() { + p.UnrollRecursionContexts(_parentctx) + }() + + defer func() { + if err := recover(); err != nil { + if v, ok := err.(antlr.RecognitionException); ok { + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + } else { + panic(err) + } + } + }() + + var _alt int + + p.EnterOuterAlt(localctx, 1) + p.SetState(38) + p.GetErrorHandler().Sync(p) + switch p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 0, p.GetParserRuleContext()) { + case 1: + localctx = NewFunctionInvocationExpressionContext(p, localctx) + p.SetParserRuleContext(localctx) + _prevctx = localctx + + { + p.SetState(24) + p.FunctionIdentifier() + } + { + p.SetState(25) + p.FunctionParameterList() + } + + case 2: + localctx = NewUnaryLogicExpressionContext(p, localctx) + p.SetParserRuleContext(localctx) + _prevctx = localctx + { + p.SetState(27) + p.Match(CESQLParserParserNOT) + } + { + p.SetState(28) + p.expression(11) + } + + case 3: + localctx = NewUnaryNumericExpressionContext(p, localctx) + p.SetParserRuleContext(localctx) + _prevctx = localctx + { + p.SetState(29) + p.Match(CESQLParserParserMINUS) + } + { + p.SetState(30) + p.expression(10) + } + + case 4: + localctx = NewExistsExpressionContext(p, localctx) + p.SetParserRuleContext(localctx) + _prevctx = localctx + { + p.SetState(31) + p.Match(CESQLParserParserEXISTS) + } + { + p.SetState(32) + p.Identifier() + } + + case 5: + localctx = NewSubExpressionContext(p, localctx) + p.SetParserRuleContext(localctx) + _prevctx = localctx + { + p.SetState(33) + p.Match(CESQLParserParserLR_BRACKET) + } + { + p.SetState(34) + p.expression(0) + } + { + p.SetState(35) + p.Match(CESQLParserParserRR_BRACKET) + } + + case 6: + localctx = NewAtomExpressionContext(p, localctx) + p.SetParserRuleContext(localctx) + _prevctx = localctx + { + p.SetState(37) + p.Atom() + } + + } + p.GetParserRuleContext().SetStop(p.GetTokenStream().LT(-1)) + p.SetState(66) + p.GetErrorHandler().Sync(p) + _alt = p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 4, p.GetParserRuleContext()) + + for _alt != 2 && _alt != antlr.ATNInvalidAltNumber { + if _alt == 1 { + if p.GetParseListeners() != nil { + p.TriggerExitRuleEvent() + } + _prevctx = localctx + p.SetState(64) + p.GetErrorHandler().Sync(p) + switch p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 3, p.GetParserRuleContext()) { + case 1: + localctx = NewBinaryMultiplicativeExpressionContext(p, NewExpressionContext(p, _parentctx, _parentState)) + p.PushNewRecursionContext(localctx, _startState, CESQLParserParserRULE_expression) + p.SetState(40) + + if !(p.Precpred(p.GetParserRuleContext(), 6)) { + panic(antlr.NewFailedPredicateException(p, "p.Precpred(p.GetParserRuleContext(), 6)", "")) + } + { + p.SetState(41) + _la = p.GetTokenStream().LA(1) + + if !(((_la)&-(0x1f+1)) == 0 && ((int64(1)< maxArity { + maxArity = a + } + } + if maxArity >= function.Arity() { + return errors.New("cannot add the variadic function, " + + "because there is already another function defined with the same name and same or greater arity") + } + + item.variadicFunction = function + return nil + } else { + if _, ok := item.fixedArgsFunctions[function.Arity()]; ok { + return errors.New("cannot add the function, " + + "because there is already another function defined with the same arity and same name") + } + + item.fixedArgsFunctions[function.Arity()] = function + return nil + } +} + +func (table functionTable) ResolveFunction(name string, args int) cesql.Function { + item := table[strings.ToUpper(name)] + if item == nil { + return nil + } + + if fn, ok := item.fixedArgsFunctions[args]; ok { + return fn + } + + if item.variadicFunction == nil || item.variadicFunction.Arity() > args { + return nil + } + + return item.variadicFunction +} + +var globalFunctionTable = functionTable{} + +func init() { + for _, fn := range []cesql.Function{ + function.IntFunction, + function.BoolFunction, + function.StringFunction, + function.IsBoolFunction, + function.IsIntFunction, + function.AbsFunction, + function.LengthFunction, + function.ConcatFunction, + function.ConcatWSFunction, + function.LowerFunction, + function.UpperFunction, + function.TrimFunction, + function.LeftFunction, + function.RightFunction, + function.SubstringFunction, + function.SubstringWithLengthFunction, + } { + if err := globalFunctionTable.AddFunction(fn); err != nil { + panic(err) + } + } +} + +func ResolveFunction(name string, args int) cesql.Function { + return globalFunctionTable.ResolveFunction(name, args) +} diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/types.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/types.go new file mode 100644 index 000000000..0c1f20078 --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/types.go @@ -0,0 +1,47 @@ +/* + Copyright 2021 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +package v2 + +type Type uint8 + +const ( + StringType Type = iota + IntegerType + BooleanType + AnyType +) + +func TypePtr(t Type) *Type { + return &t +} + +func (t Type) IsSameType(val interface{}) bool { + return TypeFromVal(val) == t +} + +func (t Type) String() string { + switch t { + case IntegerType: + return "Integer" + case BooleanType: + return "Boolean" + case StringType: + return "String" + } + return "Any" +} + +func TypeFromVal(val interface{}) Type { + switch val.(type) { + case string: + return StringType + case int32: + return IntegerType + case bool: + return BooleanType + } + return AnyType +} diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/utils/casting.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/utils/casting.go new file mode 100644 index 000000000..9cf05b004 --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/utils/casting.go @@ -0,0 +1,65 @@ +/* + Copyright 2021 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +package utils + +import ( + "fmt" + "strconv" + "strings" + + cesql "github.com/cloudevents/sdk-go/sql/v2" +) + +func Cast(val interface{}, target cesql.Type) (interface{}, error) { + if target.IsSameType(val) { + return val, nil + } + switch target { + case cesql.StringType: + switch val.(type) { + case int32: + return strconv.Itoa(int(val.(int32))), nil + case bool: + if val.(bool) { + return "true", nil + } else { + return "false", nil + } + } + // Casting to string is always defined + return fmt.Sprintf("%v", val), nil + case cesql.IntegerType: + switch val.(type) { + case string: + v, err := strconv.Atoi(val.(string)) + if err != nil { + err = fmt.Errorf("cannot cast from String to Integer: %w", err) + } + return int32(v), err + } + return 0, fmt.Errorf("undefined cast from %v to %v", cesql.TypeFromVal(val), target) + case cesql.BooleanType: + switch val.(type) { + case string: + lowerCase := strings.ToLower(val.(string)) + if lowerCase == "true" { + return true, nil + } else if lowerCase == "false" { + return false, nil + } + return false, fmt.Errorf("cannot cast String to Boolean, actual value: %v", val) + } + return false, fmt.Errorf("undefined cast from %v to %v", cesql.TypeFromVal(val), target) + } + + // AnyType doesn't need casting + return val, nil +} + +func CanCast(val interface{}, target cesql.Type) bool { + _, err := Cast(val, target) + return err == nil +} diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/utils/event.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/utils/event.go new file mode 100644 index 000000000..8525d4bf4 --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/utils/event.go @@ -0,0 +1,67 @@ +/* + Copyright 2021 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +package utils + +import ( + "fmt" + "time" + + cloudevents "github.com/cloudevents/sdk-go/v2" + "github.com/cloudevents/sdk-go/v2/binding/spec" + "github.com/cloudevents/sdk-go/v2/types" +) + +func GetAttribute(event cloudevents.Event, attributeName string) interface{} { + var val interface{} + + if a := spec.V1.Attribute(attributeName); a != nil { // Standard attribute + val = a.Get(event.Context) + } else { + val = event.Extensions()[attributeName] + } + + if val == nil { + return nil + } + + // Type cohercion + switch val.(type) { + case bool, int32, string: + return val + case int8: + return int32(val.(int8)) + case uint8: + return int32(val.(uint8)) + case int16: + return int32(val.(int16)) + case uint16: + return int32(val.(uint16)) + case uint32: + return int32(val.(uint32)) + case int64: + return int32(val.(int64)) + case uint64: + return int32(val.(uint64)) + case time.Time: + return val.(time.Time).Format(time.RFC3339Nano) + case []byte: + return types.FormatBinary(val.([]byte)) + } + return fmt.Sprintf("%v", val) +} + +func ContainsAttribute(event cloudevents.Event, attributeName string) bool { + if attributeName == "specversion" || attributeName == "id" || attributeName == "source" || attributeName == "type" { + return true + } + + if attr := spec.V1.Attribute(attributeName); attr != nil { + return attr.Get(event.Context) != nil + } + + _, ok := event.Extensions()[attributeName] + return ok +} diff --git a/vendor/github.com/cloudevents/sdk-go/v2/client/client.go b/vendor/github.com/cloudevents/sdk-go/v2/client/client.go index 0be62d7fc..ee2d51abc 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/client/client.go +++ b/vendor/github.com/cloudevents/sdk-go/v2/client/client.go @@ -128,11 +128,10 @@ func (c *ceClient) Send(ctx context.Context, e event.Event) protocol.Result { return err } - // Event has been defaulted and validated, record we are going to preform send. + // Event has been defaulted and validated, record we are going to perform send. ctx, cb := c.observabilityService.RecordSendingEvent(ctx, e) - defer cb(err) - err = c.sender.Send(ctx, (*binding.EventMessage)(&e)) + defer cb(err) return err } @@ -160,7 +159,6 @@ func (c *ceClient) Request(ctx context.Context, e event.Event) (*event.Event, pr // Event has been defaulted and validated, record we are going to perform request. ctx, cb := c.observabilityService.RecordRequestEvent(ctx, e) - defer cb(err, resp) // If provided a requester, use it to do request/response. var msg binding.Message @@ -186,7 +184,7 @@ func (c *ceClient) Request(ctx context.Context, e event.Event) (*event.Event, pr } else { resp = rs } - + defer cb(err, resp) return resp, err } diff --git a/vendor/github.com/cloudevents/sdk-go/v2/client/invoker.go b/vendor/github.com/cloudevents/sdk-go/v2/client/invoker.go index e6d11f55f..403fb0f55 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/client/invoker.go +++ b/vendor/github.com/cloudevents/sdk-go/v2/client/invoker.go @@ -81,9 +81,9 @@ func (r *receiveInvoker) Invoke(ctx context.Context, m binding.Message, respFn p var cb func(error) ctx, cb = r.observabilityService.RecordCallingInvoker(ctx, e) - defer cb(result) resp, result = r.fn.invoke(ctx, e) + defer cb(result) return }() @@ -127,6 +127,9 @@ func (r *receiveInvoker) IsResponder() bool { func computeInboundContext(message binding.Message, fallback context.Context, inboundContextDecorators []func(context.Context, binding.Message) context.Context) context.Context { result := fallback + if mctx, ok := message.(binding.MessageContext); ok { + result = cecontext.ValuesDelegating(mctx.Context(), fallback) + } for _, f := range inboundContextDecorators { result = f(result, message) } diff --git a/vendor/github.com/cloudevents/sdk-go/v2/context/delegating.go b/vendor/github.com/cloudevents/sdk-go/v2/context/delegating.go new file mode 100644 index 000000000..434a4da7a --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/v2/context/delegating.go @@ -0,0 +1,25 @@ +package context + +import "context" + +type valuesDelegating struct { + context.Context + parent context.Context +} + +// ValuesDelegating wraps a child and parent context. It will perform Value() +// lookups first on the child, and then fall back to the child. All other calls +// go solely to the child context. +func ValuesDelegating(child, parent context.Context) context.Context { + return &valuesDelegating{ + Context: child, + parent: parent, + } +} + +func (c *valuesDelegating) Value(key interface{}) interface{} { + if val := c.Context.Value(key); val != nil { + return val + } + return c.parent.Value(key) +} diff --git a/vendor/github.com/cloudevents/sdk-go/v2/event/eventcontext_v03.go b/vendor/github.com/cloudevents/sdk-go/v2/event/eventcontext_v03.go index 561f4c5df..c511c81c4 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/event/eventcontext_v03.go +++ b/vendor/github.com/cloudevents/sdk-go/v2/event/eventcontext_v03.go @@ -20,6 +20,17 @@ const ( CloudEventsVersionV03 = "0.3" ) +var specV03Attributes = map[string]struct{}{ + "type": {}, + "source": {}, + "subject": {}, + "id": {}, + "time": {}, + "schemaurl": {}, + "datacontenttype": {}, + "datacontentencoding": {}, +} + // EventContextV03 represents the non-data attributes of a CloudEvents v0.3 // event. type EventContextV03 struct { @@ -78,11 +89,17 @@ func (ec EventContextV03) ExtensionAs(name string, obj interface{}) error { } } -// SetExtension adds the extension 'name' with value 'value' to the CloudEvents context. +// SetExtension adds the extension 'name' with value 'value' to the CloudEvents +// context. This function fails if the name uses a reserved event context key. func (ec *EventContextV03) SetExtension(name string, value interface{}) error { if ec.Extensions == nil { ec.Extensions = make(map[string]interface{}) } + + if _, ok := specV03Attributes[strings.ToLower(name)]; ok { + return fmt.Errorf("bad key %q: CloudEvents spec attribute MUST NOT be overwritten by extension", name) + } + if value == nil { delete(ec.Extensions, name) if len(ec.Extensions) == 0 { diff --git a/vendor/github.com/cloudevents/sdk-go/v2/event/eventcontext_v1.go b/vendor/github.com/cloudevents/sdk-go/v2/event/eventcontext_v1.go index 01f97586f..8f164502b 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/event/eventcontext_v1.go +++ b/vendor/github.com/cloudevents/sdk-go/v2/event/eventcontext_v1.go @@ -21,6 +21,17 @@ const ( CloudEventsVersionV1 = "1.0" ) +var specV1Attributes = map[string]struct{}{ + "id": {}, + "source": {}, + "type": {}, + "datacontenttype": {}, + "subject": {}, + "time": {}, + "specversion": {}, + "dataschema": {}, +} + // EventContextV1 represents the non-data attributes of a CloudEvents v1.0 // event. type EventContextV1 struct { @@ -73,13 +84,18 @@ func (ec EventContextV1) ExtensionAs(name string, obj interface{}) error { return fmt.Errorf("unknown extension type %T", obj) } -// SetExtension adds the extension 'name' with value 'value' to the CloudEvents context. -// This function fails if the name doesn't respect the regex ^[a-zA-Z0-9]+$ +// SetExtension adds the extension 'name' with value 'value' to the CloudEvents +// context. This function fails if the name doesn't respect the regex +// ^[a-zA-Z0-9]+$ or if the name uses a reserved event context key. func (ec *EventContextV1) SetExtension(name string, value interface{}) error { if err := validateExtensionName(name); err != nil { return err } + if _, ok := specV1Attributes[strings.ToLower(name)]; ok { + return fmt.Errorf("bad key %q: CloudEvents spec attribute MUST NOT be overwritten by extension", name) + } + name = strings.ToLower(name) if ec.Extensions == nil { ec.Extensions = make(map[string]interface{}) diff --git a/vendor/github.com/cloudevents/sdk-go/v2/go.mod b/vendor/github.com/cloudevents/sdk-go/v2/go.mod index 40a2d282b..3f98f1dd2 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/go.mod +++ b/vendor/github.com/cloudevents/sdk-go/v2/go.mod @@ -15,6 +15,7 @@ require ( go.uber.org/multierr v1.1.0 // indirect go.uber.org/zap v1.10.0 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e + golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/yaml.v2 v2.3.0 // indirect ) diff --git a/vendor/github.com/cloudevents/sdk-go/v2/go.sum b/vendor/github.com/cloudevents/sdk-go/v2/go.sum index b893d87b1..991e8e152 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/go.sum +++ b/vendor/github.com/cloudevents/sdk-go/v2/go.sum @@ -37,6 +37,8 @@ go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/context.go b/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/context.go new file mode 100644 index 000000000..0eec396a1 --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/context.go @@ -0,0 +1,48 @@ +/* + Copyright 2021 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +package http + +import ( + "context" + + nethttp "net/http" + "net/url" +) + +type requestKey struct{} + +// RequestData holds the http.Request information subset that can be +// used to retrieve HTTP information for an incoming CloudEvent. +type RequestData struct { + URL *url.URL + Header nethttp.Header + RemoteAddr string + Host string +} + +// WithRequestDataAtContext uses the http.Request to add RequestData +// information to the Context. +func WithRequestDataAtContext(ctx context.Context, r *nethttp.Request) context.Context { + if r == nil { + return ctx + } + + return context.WithValue(ctx, requestKey{}, &RequestData{ + URL: r.URL, + Header: r.Header, + RemoteAddr: r.RemoteAddr, + Host: r.Host, + }) +} + +// RequestDataFromContext retrieves RequestData from the Context. +// If not set nil is returned. +func RequestDataFromContext(ctx context.Context) *RequestData { + if req := ctx.Value(requestKey{}); req != nil { + return req.(*RequestData) + } + return nil +} diff --git a/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/options.go b/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/options.go index 55031939c..5e400905a 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/options.go +++ b/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/options.go @@ -248,7 +248,7 @@ func WithDefaultOptionsHandlerFunc(methods []string, rate int, origins []string, if p == nil { return fmt.Errorf("http OPTIONS handler func can not set nil protocol") } - p.OptionsHandlerFn = p.DeleteHandlerFn + p.OptionsHandlerFn = p.OptionsHandler p.WebhookConfig = &WebhookConfig{ AllowedMethods: methods, AllowedRate: &rate, @@ -277,3 +277,25 @@ func WithIsRetriableFunc(isRetriable IsRetriable) Option { return nil } } + +func WithRateLimiter(rl RateLimiter) Option { + return func(p *Protocol) error { + if p == nil { + return fmt.Errorf("http OPTIONS handler func can not set nil protocol") + } + p.limiter = rl + return nil + } +} + +// WithRequestDataAtContextMiddleware adds to the Context RequestData. +// This enables a user's dispatch handler to inspect HTTP request information by +// retrieving it from the Context. +func WithRequestDataAtContextMiddleware() Option { + return WithMiddleware(func(next nethttp.Handler) nethttp.Handler { + return nethttp.HandlerFunc(func(w nethttp.ResponseWriter, r *nethttp.Request) { + ctx := WithRequestDataAtContext(r.Context(), r) + next.ServeHTTP(w, r.WithContext(ctx)) + }) + }) +} diff --git a/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/protocol.go b/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/protocol.go index a17028795..7ca5ad271 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/protocol.go +++ b/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/protocol.go @@ -13,6 +13,7 @@ import ( "io" "net/http" "net/url" + "strconv" "sync" "sync/atomic" "time" @@ -86,6 +87,7 @@ type Protocol struct { server *http.Server handlerRegistered bool middleware []Middleware + limiter RateLimiter isRetriableFunc IsRetriable } @@ -115,6 +117,10 @@ func New(opts ...Option) (*Protocol, error) { p.isRetriableFunc = defaultIsRetriableFunc } + if p.limiter == nil { + p.limiter = noOpLimiter{} + } + return p, nil } @@ -277,6 +283,20 @@ func (p *Protocol) Respond(ctx context.Context) (binding.Message, protocol.Respo // ServeHTTP implements http.Handler. // Blocks until ResponseFn is invoked. func (p *Protocol) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + // always apply limiter first using req context + ok, reset, err := p.limiter.Allow(req.Context(), req) + if err != nil { + p.incoming <- msgErr{msg: nil, err: fmt.Errorf("unable to acquire rate limit token: %w", err)} + rw.WriteHeader(http.StatusInternalServerError) + return + } + + if !ok { + rw.Header().Add("Retry-After", strconv.Itoa(int(reset))) + http.Error(rw, "limit exceeded", 429) + return + } + // Filter the GET style methods: switch req.Method { case http.MethodOptions: diff --git a/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/protocol_rate.go b/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/protocol_rate.go new file mode 100644 index 000000000..9c4c10a29 --- /dev/null +++ b/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/protocol_rate.go @@ -0,0 +1,34 @@ +/* + Copyright 2021 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +package http + +import ( + "context" + "net/http" +) + +type RateLimiter interface { + // Allow attempts to take one token from the rate limiter for the specified + // request. It returns ok when this operation was successful. In case ok is + // false, reset will indicate the time in seconds when it is safe to perform + // another attempt. An error is returned when this operation failed, e.g. due to + // a backend error. + Allow(ctx context.Context, r *http.Request) (ok bool, reset uint64, err error) + // Close terminates rate limiter and cleans up any data structures or + // connections that may remain open. After a store is stopped, Take() should + // always return zero values. + Close(ctx context.Context) error +} + +type noOpLimiter struct{} + +func (n noOpLimiter) Allow(ctx context.Context, r *http.Request) (bool, uint64, error) { + return true, 0, nil +} + +func (n noOpLimiter) Close(ctx context.Context) error { + return nil +} diff --git a/vendor/github.com/containerd/containerd/errdefs/errors.go b/vendor/github.com/containerd/containerd/errdefs/errors.go index 05a35228c..876225597 100644 --- a/vendor/github.com/containerd/containerd/errdefs/errors.go +++ b/vendor/github.com/containerd/containerd/errdefs/errors.go @@ -17,7 +17,7 @@ // Package errdefs defines the common errors used throughout containerd // packages. // -// Use with errors.Wrap and error.Wrapf to add context to an error. +// Use with fmt.Errorf to add context to an error. // // To detect an error class, use the IsXXX functions to tell whether an error // is of a certain type. @@ -28,8 +28,7 @@ package errdefs import ( "context" - - "github.com/pkg/errors" + "errors" ) // Definitions of common error types used throughout containerd. All containerd diff --git a/vendor/github.com/containerd/containerd/errdefs/grpc.go b/vendor/github.com/containerd/containerd/errdefs/grpc.go index 209f63bd0..7a9b33e05 100644 --- a/vendor/github.com/containerd/containerd/errdefs/grpc.go +++ b/vendor/github.com/containerd/containerd/errdefs/grpc.go @@ -18,9 +18,9 @@ package errdefs import ( "context" + "fmt" "strings" - "github.com/pkg/errors" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -68,9 +68,9 @@ func ToGRPC(err error) error { // ToGRPCf maps the error to grpc error codes, assembling the formatting string // and combining it with the target error string. // -// This is equivalent to errors.ToGRPC(errors.Wrapf(err, format, args...)) +// This is equivalent to errdefs.ToGRPC(fmt.Errorf("%s: %w", fmt.Sprintf(format, args...), err)) func ToGRPCf(err error, format string, args ...interface{}) error { - return ToGRPC(errors.Wrapf(err, format, args...)) + return ToGRPC(fmt.Errorf("%s: %w", fmt.Sprintf(format, args...), err)) } // FromGRPC returns the underlying error from a grpc service based on the grpc error code @@ -104,9 +104,9 @@ func FromGRPC(err error) error { msg := rebaseMessage(cls, err) if msg != "" { - err = errors.Wrap(cls, msg) + err = fmt.Errorf("%s: %w", msg, cls) } else { - err = errors.WithStack(cls) + err = cls } return err diff --git a/vendor/github.com/containerd/containerd/log/context.go b/vendor/github.com/containerd/containerd/log/context.go index 37b6a7d1c..0db9562b8 100644 --- a/vendor/github.com/containerd/containerd/log/context.go +++ b/vendor/github.com/containerd/containerd/log/context.go @@ -52,7 +52,8 @@ const ( // WithLogger returns a new context with the provided logger. Use in // combination with logger.WithField(s) for great effect. func WithLogger(ctx context.Context, logger *logrus.Entry) context.Context { - return context.WithValue(ctx, loggerKey{}, logger) + e := logger.WithContext(ctx) + return context.WithValue(ctx, loggerKey{}, e) } // GetLogger retrieves the current logger from the context. If no logger is @@ -61,7 +62,7 @@ func GetLogger(ctx context.Context) *logrus.Entry { logger := ctx.Value(loggerKey{}) if logger == nil { - return L + return L.WithContext(ctx) } return logger.(*logrus.Entry) diff --git a/vendor/github.com/containerd/containerd/pkg/userns/userns_unsupported.go b/vendor/github.com/containerd/containerd/pkg/userns/userns_unsupported.go index aab756fd2..4f8d7dd2d 100644 --- a/vendor/github.com/containerd/containerd/pkg/userns/userns_unsupported.go +++ b/vendor/github.com/containerd/containerd/pkg/userns/userns_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux /* diff --git a/vendor/github.com/containerd/containerd/platforms/compare.go b/vendor/github.com/containerd/containerd/platforms/compare.go index c7657e186..3913ef663 100644 --- a/vendor/github.com/containerd/containerd/platforms/compare.go +++ b/vendor/github.com/containerd/containerd/platforms/compare.go @@ -38,12 +38,22 @@ func platformVector(platform specs.Platform) []specs.Platform { switch platform.Architecture { case "amd64": + if amd64Version, err := strconv.Atoi(strings.TrimPrefix(platform.Variant, "v")); err == nil && amd64Version > 1 { + for amd64Version--; amd64Version >= 1; amd64Version-- { + vector = append(vector, specs.Platform{ + Architecture: platform.Architecture, + OS: platform.OS, + OSVersion: platform.OSVersion, + OSFeatures: platform.OSFeatures, + Variant: "v" + strconv.Itoa(amd64Version), + }) + } + } vector = append(vector, specs.Platform{ Architecture: "386", OS: platform.OS, OSVersion: platform.OSVersion, OSFeatures: platform.OSFeatures, - Variant: platform.Variant, }) case "arm": if armVersion, err := strconv.Atoi(strings.TrimPrefix(platform.Variant, "v")); err == nil && armVersion > 5 { diff --git a/vendor/github.com/containerd/containerd/platforms/cpuinfo.go b/vendor/github.com/containerd/containerd/platforms/cpuinfo.go index 4a7177e31..046e0356d 100644 --- a/vendor/github.com/containerd/containerd/platforms/cpuinfo.go +++ b/vendor/github.com/containerd/containerd/platforms/cpuinfo.go @@ -18,6 +18,7 @@ package platforms import ( "bufio" + "fmt" "os" "runtime" "strings" @@ -25,7 +26,6 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/log" - "github.com/pkg/errors" ) // Present the ARM instruction set architecture, eg: v7, v8 @@ -48,7 +48,7 @@ func cpuVariant() string { // by ourselves. We can just parse these information from /proc/cpuinfo func getCPUInfo(pattern string) (info string, err error) { if !isLinuxOS(runtime.GOOS) { - return "", errors.Wrapf(errdefs.ErrNotImplemented, "getCPUInfo for OS %s", runtime.GOOS) + return "", fmt.Errorf("getCPUInfo for OS %s: %w", runtime.GOOS, errdefs.ErrNotImplemented) } cpuinfo, err := os.Open("/proc/cpuinfo") @@ -75,7 +75,7 @@ func getCPUInfo(pattern string) (info string, err error) { return "", err } - return "", errors.Wrapf(errdefs.ErrNotFound, "getCPUInfo for pattern: %s", pattern) + return "", fmt.Errorf("getCPUInfo for pattern: %s: %w", pattern, errdefs.ErrNotFound) } func getCPUVariant() string { diff --git a/vendor/github.com/containerd/containerd/platforms/database.go b/vendor/github.com/containerd/containerd/platforms/database.go index 6ede94061..dbe9957ca 100644 --- a/vendor/github.com/containerd/containerd/platforms/database.go +++ b/vendor/github.com/containerd/containerd/platforms/database.go @@ -38,7 +38,7 @@ func isLinuxOS(os string) bool { // The OS value should be normalized before calling this function. func isKnownOS(os string) bool { switch os { - case "aix", "android", "darwin", "dragonfly", "freebsd", "hurd", "illumos", "js", "linux", "nacl", "netbsd", "openbsd", "plan9", "solaris", "windows", "zos": + case "aix", "android", "darwin", "dragonfly", "freebsd", "hurd", "illumos", "ios", "js", "linux", "nacl", "netbsd", "openbsd", "plan9", "solaris", "windows", "zos": return true } return false @@ -60,7 +60,7 @@ func isArmArch(arch string) bool { // The arch value should be normalized before being passed to this function. func isKnownArch(arch string) bool { switch arch { - case "386", "amd64", "amd64p32", "arm", "armbe", "arm64", "arm64be", "ppc64", "ppc64le", "mips", "mipsle", "mips64", "mips64le", "mips64p32", "mips64p32le", "ppc", "riscv", "riscv64", "s390", "s390x", "sparc", "sparc64", "wasm": + case "386", "amd64", "amd64p32", "arm", "armbe", "arm64", "arm64be", "ppc64", "ppc64le", "loong64", "mips", "mipsle", "mips64", "mips64le", "mips64p32", "mips64p32le", "ppc", "riscv", "riscv64", "s390", "s390x", "sparc", "sparc64", "wasm": return true } return false @@ -86,9 +86,11 @@ func normalizeArch(arch, variant string) (string, string) { case "i386": arch = "386" variant = "" - case "x86_64", "x86-64": + case "x86_64", "x86-64", "amd64": arch = "amd64" - variant = "" + if variant == "v1" { + variant = "" + } case "aarch64", "arm64": arch = "arm64" switch variant { diff --git a/vendor/github.com/containerd/containerd/platforms/defaults.go b/vendor/github.com/containerd/containerd/platforms/defaults.go index cb77fbc9f..cfa3ff34a 100644 --- a/vendor/github.com/containerd/containerd/platforms/defaults.go +++ b/vendor/github.com/containerd/containerd/platforms/defaults.go @@ -16,27 +16,11 @@ package platforms -import ( - "runtime" - - specs "github.com/opencontainers/image-spec/specs-go/v1" -) - // DefaultString returns the default string specifier for the platform. func DefaultString() string { return Format(DefaultSpec()) } -// DefaultSpec returns the current platform's default platform specification. -func DefaultSpec() specs.Platform { - return specs.Platform{ - OS: runtime.GOOS, - Architecture: runtime.GOARCH, - // The Variant field will be empty if arch != ARM. - Variant: cpuVariant(), - } -} - // DefaultStrict returns strict form of Default. func DefaultStrict() MatchComparer { return OnlyStrict(DefaultSpec()) diff --git a/vendor/github.com/containerd/containerd/platforms/defaults_darwin.go b/vendor/github.com/containerd/containerd/platforms/defaults_darwin.go new file mode 100644 index 000000000..e249fe48d --- /dev/null +++ b/vendor/github.com/containerd/containerd/platforms/defaults_darwin.go @@ -0,0 +1,45 @@ +//go:build darwin +// +build darwin + +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package platforms + +import ( + "runtime" + + specs "github.com/opencontainers/image-spec/specs-go/v1" +) + +// DefaultSpec returns the current platform's default platform specification. +func DefaultSpec() specs.Platform { + return specs.Platform{ + OS: runtime.GOOS, + Architecture: runtime.GOARCH, + // The Variant field will be empty if arch != ARM. + Variant: cpuVariant(), + } +} + +// Default returns the default matcher for the platform. +func Default() MatchComparer { + return Ordered(DefaultSpec(), specs.Platform{ + // darwin runtime also supports Linux binary via runu/LKL + OS: "linux", + Architecture: runtime.GOARCH, + }) +} diff --git a/vendor/github.com/containerd/containerd/platforms/defaults_unix.go b/vendor/github.com/containerd/containerd/platforms/defaults_unix.go index e8a7d5ffa..49690f1b3 100644 --- a/vendor/github.com/containerd/containerd/platforms/defaults_unix.go +++ b/vendor/github.com/containerd/containerd/platforms/defaults_unix.go @@ -1,4 +1,5 @@ -// +build !windows +//go:build !windows && !darwin +// +build !windows,!darwin /* Copyright The containerd Authors. @@ -18,6 +19,22 @@ package platforms +import ( + "runtime" + + specs "github.com/opencontainers/image-spec/specs-go/v1" +) + +// DefaultSpec returns the current platform's default platform specification. +func DefaultSpec() specs.Platform { + return specs.Platform{ + OS: runtime.GOOS, + Architecture: runtime.GOARCH, + // The Variant field will be empty if arch != ARM. + Variant: cpuVariant(), + } +} + // Default returns the default matcher for the platform. func Default() MatchComparer { return Only(DefaultSpec()) diff --git a/vendor/github.com/containerd/containerd/platforms/defaults_windows.go b/vendor/github.com/containerd/containerd/platforms/defaults_windows.go index 0c380e3b7..c1aaf72ca 100644 --- a/vendor/github.com/containerd/containerd/platforms/defaults_windows.go +++ b/vendor/github.com/containerd/containerd/platforms/defaults_windows.go @@ -1,5 +1,3 @@ -// +build windows - /* Copyright The containerd Authors. @@ -29,6 +27,18 @@ import ( "golang.org/x/sys/windows" ) +// DefaultSpec returns the current platform's default platform specification. +func DefaultSpec() specs.Platform { + major, minor, build := windows.RtlGetNtVersionNumbers() + return specs.Platform{ + OS: runtime.GOOS, + Architecture: runtime.GOARCH, + OSVersion: fmt.Sprintf("%d.%d.%d", major, minor, build), + // The Variant field will be empty if arch != ARM. + Variant: cpuVariant(), + } +} + type matchComparer struct { defaults Matcher osVersionPrefix string diff --git a/vendor/github.com/containerd/containerd/platforms/platforms.go b/vendor/github.com/containerd/containerd/platforms/platforms.go index 088bdea05..8f955d036 100644 --- a/vendor/github.com/containerd/containerd/platforms/platforms.go +++ b/vendor/github.com/containerd/containerd/platforms/platforms.go @@ -107,6 +107,8 @@ package platforms import ( + "fmt" + "path" "regexp" "runtime" "strconv" @@ -114,7 +116,6 @@ import ( "github.com/containerd/containerd/errdefs" specs "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" ) var ( @@ -166,14 +167,14 @@ func (m *matcher) String() string { func Parse(specifier string) (specs.Platform, error) { if strings.Contains(specifier, "*") { // TODO(stevvooe): need to work out exact wildcard handling - return specs.Platform{}, errors.Wrapf(errdefs.ErrInvalidArgument, "%q: wildcards not yet supported", specifier) + return specs.Platform{}, fmt.Errorf("%q: wildcards not yet supported: %w", specifier, errdefs.ErrInvalidArgument) } parts := strings.Split(specifier, "/") for _, part := range parts { if !specifierRe.MatchString(part) { - return specs.Platform{}, errors.Wrapf(errdefs.ErrInvalidArgument, "%q is an invalid component of %q: platform specifier component must match %q", part, specifier, specifierRe.String()) + return specs.Platform{}, fmt.Errorf("%q is an invalid component of %q: platform specifier component must match %q: %w", part, specifier, specifierRe.String(), errdefs.ErrInvalidArgument) } } @@ -205,7 +206,7 @@ func Parse(specifier string) (specs.Platform, error) { return p, nil } - return specs.Platform{}, errors.Wrapf(errdefs.ErrInvalidArgument, "%q: unknown operating system or architecture", specifier) + return specs.Platform{}, fmt.Errorf("%q: unknown operating system or architecture: %w", specifier, errdefs.ErrInvalidArgument) case 2: // In this case, we treat as a regular os/arch pair. We don't care // about whether or not we know of the platform. @@ -227,7 +228,7 @@ func Parse(specifier string) (specs.Platform, error) { return p, nil } - return specs.Platform{}, errors.Wrapf(errdefs.ErrInvalidArgument, "%q: cannot parse platform specifier", specifier) + return specs.Platform{}, fmt.Errorf("%q: cannot parse platform specifier: %w", specifier, errdefs.ErrInvalidArgument) } // MustParse is like Parses but panics if the specifier cannot be parsed. @@ -246,20 +247,7 @@ func Format(platform specs.Platform) string { return "unknown" } - return joinNotEmpty(platform.OS, platform.Architecture, platform.Variant) -} - -func joinNotEmpty(s ...string) string { - var ss []string - for _, s := range s { - if s == "" { - continue - } - - ss = append(ss, s) - } - - return strings.Join(ss, "/") + return path.Join(platform.OS, platform.Architecture, platform.Variant) } // Normalize validates and translate the platform to the canonical value. @@ -269,10 +257,5 @@ func joinNotEmpty(s ...string) string { func Normalize(platform specs.Platform) specs.Platform { platform.OS = normalizeOS(platform.OS) platform.Architecture, platform.Variant = normalizeArch(platform.Architecture, platform.Variant) - - // these fields are deprecated, remove them - platform.OSFeatures = nil - platform.OSVersion = "" - return platform } diff --git a/vendor/github.com/containerd/containerd/sys/epoll.go b/vendor/github.com/containerd/containerd/sys/epoll.go index 28d6c2cab..73a57013f 100644 --- a/vendor/github.com/containerd/containerd/sys/epoll.go +++ b/vendor/github.com/containerd/containerd/sys/epoll.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux /* diff --git a/vendor/github.com/containerd/containerd/sys/fds.go b/vendor/github.com/containerd/containerd/sys/fds.go index db3cf702f..a71a9cd7e 100644 --- a/vendor/github.com/containerd/containerd/sys/fds.go +++ b/vendor/github.com/containerd/containerd/sys/fds.go @@ -1,3 +1,4 @@ +//go:build !windows && !darwin // +build !windows,!darwin /* @@ -19,14 +20,14 @@ package sys import ( - "io/ioutil" + "os" "path/filepath" "strconv" ) // GetOpenFds returns the number of open fds for the process provided by pid func GetOpenFds(pid int) (int, error) { - dirs, err := ioutil.ReadDir(filepath.Join("/proc", strconv.Itoa(pid), "fd")) + dirs, err := os.ReadDir(filepath.Join("/proc", strconv.Itoa(pid), "fd")) if err != nil { return -1, err } diff --git a/vendor/github.com/containerd/containerd/sys/filesys_unix.go b/vendor/github.com/containerd/containerd/sys/filesys_unix.go index d8329af9f..805a7a736 100644 --- a/vendor/github.com/containerd/containerd/sys/filesys_unix.go +++ b/vendor/github.com/containerd/containerd/sys/filesys_unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows /* diff --git a/vendor/github.com/containerd/containerd/sys/filesys_windows.go b/vendor/github.com/containerd/containerd/sys/filesys_windows.go index a9198ef39..87ebacc20 100644 --- a/vendor/github.com/containerd/containerd/sys/filesys_windows.go +++ b/vendor/github.com/containerd/containerd/sys/filesys_windows.go @@ -1,5 +1,3 @@ -// +build windows - /* Copyright The containerd Authors. @@ -19,6 +17,7 @@ package sys import ( + "fmt" "os" "path/filepath" "regexp" @@ -29,7 +28,6 @@ import ( "unsafe" "github.com/Microsoft/hcsshim" - "github.com/pkg/errors" "golang.org/x/sys/windows" ) @@ -270,7 +268,7 @@ func ForceRemoveAll(path string) error { snapshotDir := filepath.Join(path, snapshotPlugin, "snapshots") if stat, err := os.Stat(snapshotDir); err == nil && stat.IsDir() { if err := cleanupWCOWLayers(snapshotDir); err != nil { - return errors.Wrapf(err, "failed to cleanup WCOW layers in %s", snapshotDir) + return fmt.Errorf("failed to cleanup WCOW layers in %s: %w", snapshotDir, err) } } @@ -280,12 +278,22 @@ func ForceRemoveAll(path string) error { func cleanupWCOWLayers(root string) error { // See snapshots/windows/windows.go getSnapshotDir() var layerNums []int + var rmLayerNums []int if err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { if path != root && info.IsDir() { - if layerNum, err := strconv.Atoi(filepath.Base(path)); err == nil { - layerNums = append(layerNums, layerNum) + name := filepath.Base(path) + if strings.HasPrefix(name, "rm-") { + layerNum, err := strconv.Atoi(strings.TrimPrefix(name, "rm-")) + if err != nil { + return err + } + rmLayerNums = append(rmLayerNums, layerNum) } else { - return err + layerNum, err := strconv.Atoi(name) + if err != nil { + return err + } + layerNums = append(layerNums, layerNum) } return filepath.SkipDir } @@ -295,8 +303,14 @@ func cleanupWCOWLayers(root string) error { return err } - sort.Sort(sort.Reverse(sort.IntSlice(layerNums))) + sort.Sort(sort.Reverse(sort.IntSlice(rmLayerNums))) + for _, rmLayerNum := range rmLayerNums { + if err := cleanupWCOWLayer(filepath.Join(root, "rm-"+strconv.Itoa(rmLayerNum))); err != nil { + return err + } + } + sort.Sort(sort.Reverse(sort.IntSlice(layerNums))) for _, layerNum := range layerNums { if err := cleanupWCOWLayer(filepath.Join(root, strconv.Itoa(layerNum))); err != nil { return err @@ -311,19 +325,20 @@ func cleanupWCOWLayer(layerPath string) error { HomeDir: filepath.Dir(layerPath), } - // ERROR_DEV_NOT_EXIST is returned if the layer is not currently prepared. + // ERROR_DEV_NOT_EXIST is returned if the layer is not currently prepared or activated. + // ERROR_FLT_INSTANCE_NOT_FOUND is returned if the layer is currently activated but not prepared. if err := hcsshim.UnprepareLayer(info, filepath.Base(layerPath)); err != nil { - if hcserror, ok := err.(*hcsshim.HcsError); !ok || hcserror.Err != windows.ERROR_DEV_NOT_EXIST { - return errors.Wrapf(err, "failed to unprepare %s", layerPath) + if hcserror, ok := err.(*hcsshim.HcsError); !ok || (hcserror.Err != windows.ERROR_DEV_NOT_EXIST && hcserror.Err != syscall.Errno(windows.ERROR_FLT_INSTANCE_NOT_FOUND)) { + return fmt.Errorf("failed to unprepare %s: %w", layerPath, err) } } if err := hcsshim.DeactivateLayer(info, filepath.Base(layerPath)); err != nil { - return errors.Wrapf(err, "failed to deactivate %s", layerPath) + return fmt.Errorf("failed to deactivate %s: %w", layerPath, err) } if err := hcsshim.DestroyLayer(info, filepath.Base(layerPath)); err != nil { - return errors.Wrapf(err, "failed to destroy %s", layerPath) + return fmt.Errorf("failed to destroy %s: %w", layerPath, err) } return nil diff --git a/vendor/github.com/containerd/containerd/sys/mount_linux.go b/vendor/github.com/containerd/containerd/sys/mount_linux.go deleted file mode 100644 index a21045529..000000000 --- a/vendor/github.com/containerd/containerd/sys/mount_linux.go +++ /dev/null @@ -1,145 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package sys - -import ( - "runtime" - "syscall" - "unsafe" - - "github.com/containerd/containerd/log" - "github.com/pkg/errors" - "golang.org/x/sys/unix" -) - -// FMountat performs mount from the provided directory. -func FMountat(dirfd uintptr, source, target, fstype string, flags uintptr, data string) error { - var ( - sourceP, targetP, fstypeP, dataP *byte - pid uintptr - err error - errno, status syscall.Errno - ) - - sourceP, err = syscall.BytePtrFromString(source) - if err != nil { - return err - } - - targetP, err = syscall.BytePtrFromString(target) - if err != nil { - return err - } - - fstypeP, err = syscall.BytePtrFromString(fstype) - if err != nil { - return err - } - - if data != "" { - dataP, err = syscall.BytePtrFromString(data) - if err != nil { - return err - } - } - - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - var pipefds [2]int - if err := syscall.Pipe2(pipefds[:], syscall.O_CLOEXEC); err != nil { - return errors.Wrap(err, "failed to open pipe") - } - - defer func() { - // close both ends of the pipe in a deferred function, since open file - // descriptor table is shared with child - syscall.Close(pipefds[0]) - syscall.Close(pipefds[1]) - }() - - pid, errno = forkAndMountat(dirfd, - uintptr(unsafe.Pointer(sourceP)), - uintptr(unsafe.Pointer(targetP)), - uintptr(unsafe.Pointer(fstypeP)), - flags, - uintptr(unsafe.Pointer(dataP)), - pipefds[1], - ) - - if errno != 0 { - return errors.Wrap(errno, "failed to fork thread") - } - - defer func() { - _, err := unix.Wait4(int(pid), nil, 0, nil) - for err == syscall.EINTR { - _, err = unix.Wait4(int(pid), nil, 0, nil) - } - - if err != nil { - log.L.WithError(err).Debugf("failed to find pid=%d process", pid) - } - }() - - _, _, errno = syscall.RawSyscall(syscall.SYS_READ, - uintptr(pipefds[0]), - uintptr(unsafe.Pointer(&status)), - unsafe.Sizeof(status)) - if errno != 0 { - return errors.Wrap(errno, "failed to read pipe") - } - - if status != 0 { - return errors.Wrap(status, "failed to mount") - } - - return nil -} - -// forkAndMountat will fork thread, change working dir and mount. -// -// precondition: the runtime OS thread must be locked. -func forkAndMountat(dirfd uintptr, source, target, fstype, flags, data uintptr, pipefd int) (pid uintptr, errno syscall.Errno) { - - // block signal during clone - beforeFork() - - // the cloned thread shares the open file descriptor, but the thread - // never be reused by runtime. - pid, _, errno = syscall.RawSyscall6(syscall.SYS_CLONE, uintptr(syscall.SIGCHLD)|syscall.CLONE_FILES, 0, 0, 0, 0, 0) - if errno != 0 || pid != 0 { - // restore all signals - afterFork() - return - } - - // restore all signals - afterForkInChild() - - // change working dir - _, _, errno = syscall.RawSyscall(syscall.SYS_FCHDIR, dirfd, 0, 0) - if errno != 0 { - goto childerr - } - _, _, errno = syscall.RawSyscall6(syscall.SYS_MOUNT, source, target, fstype, flags, data, 0) - -childerr: - _, _, errno = syscall.RawSyscall(syscall.SYS_WRITE, uintptr(pipefd), uintptr(unsafe.Pointer(&errno)), unsafe.Sizeof(errno)) - syscall.RawSyscall(syscall.SYS_EXIT, uintptr(errno), 0, 0) - panic("unreachable") -} diff --git a/vendor/github.com/containerd/containerd/sys/oom_linux.go b/vendor/github.com/containerd/containerd/sys/oom_linux.go index 82a347c6f..bb2a3eafb 100644 --- a/vendor/github.com/containerd/containerd/sys/oom_linux.go +++ b/vendor/github.com/containerd/containerd/sys/oom_linux.go @@ -18,7 +18,6 @@ package sys import ( "fmt" - "io/ioutil" "os" "strconv" "strings" @@ -69,7 +68,7 @@ func SetOOMScore(pid, score int) error { // no oom score is set, or a sore is set to 0. func GetOOMScoreAdj(pid int) (int, error) { path := fmt.Sprintf("/proc/%d/oom_score_adj", pid) - data, err := ioutil.ReadFile(path) + data, err := os.ReadFile(path) if err != nil { return 0, err } diff --git a/vendor/github.com/containerd/containerd/sys/oom_unsupported.go b/vendor/github.com/containerd/containerd/sys/oom_unsupported.go index f5d7e9786..fa0db5a10 100644 --- a/vendor/github.com/containerd/containerd/sys/oom_unsupported.go +++ b/vendor/github.com/containerd/containerd/sys/oom_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux /* diff --git a/vendor/github.com/containerd/containerd/sys/socket_unix.go b/vendor/github.com/containerd/containerd/sys/socket_unix.go index b67cc1fa3..367e19cad 100644 --- a/vendor/github.com/containerd/containerd/sys/socket_unix.go +++ b/vendor/github.com/containerd/containerd/sys/socket_unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows /* @@ -19,11 +20,11 @@ package sys import ( + "fmt" "net" "os" "path/filepath" - "github.com/pkg/errors" "golang.org/x/sys/unix" ) @@ -31,7 +32,7 @@ import ( func CreateUnixSocket(path string) (net.Listener, error) { // BSDs have a 104 limit if len(path) > 104 { - return nil, errors.Errorf("%q: unix socket path too long (> 104)", path) + return nil, fmt.Errorf("%q: unix socket path too long (> 104)", path) } if err := os.MkdirAll(filepath.Dir(path), 0660); err != nil { return nil, err diff --git a/vendor/github.com/containerd/containerd/sys/socket_windows.go b/vendor/github.com/containerd/containerd/sys/socket_windows.go index 3ee7679b4..1ae12bc51 100644 --- a/vendor/github.com/containerd/containerd/sys/socket_windows.go +++ b/vendor/github.com/containerd/containerd/sys/socket_windows.go @@ -1,5 +1,3 @@ -// +build windows - /* Copyright The containerd Authors. diff --git a/vendor/github.com/containerd/containerd/sys/stat_bsd.go b/vendor/github.com/containerd/containerd/sys/stat_bsd.go deleted file mode 100644 index 4f03cd6cb..000000000 --- a/vendor/github.com/containerd/containerd/sys/stat_bsd.go +++ /dev/null @@ -1,44 +0,0 @@ -// +build darwin freebsd netbsd - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package sys - -import ( - "syscall" - "time" -) - -// StatAtime returns the access time from a stat struct -func StatAtime(st *syscall.Stat_t) syscall.Timespec { - return st.Atimespec -} - -// StatCtime returns the created time from a stat struct -func StatCtime(st *syscall.Stat_t) syscall.Timespec { - return st.Ctimespec -} - -// StatMtime returns the modified time from a stat struct -func StatMtime(st *syscall.Stat_t) syscall.Timespec { - return st.Mtimespec -} - -// StatATimeAsTime returns the access time as a time.Time -func StatATimeAsTime(st *syscall.Stat_t) time.Time { - return time.Unix(int64(st.Atimespec.Sec), int64(st.Atimespec.Nsec)) // nolint: unconvert -} diff --git a/vendor/github.com/containerd/containerd/sys/stat_openbsd.go b/vendor/github.com/containerd/containerd/sys/stat_openbsd.go deleted file mode 100644 index ec3b9df69..000000000 --- a/vendor/github.com/containerd/containerd/sys/stat_openbsd.go +++ /dev/null @@ -1,45 +0,0 @@ -// +build openbsd - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package sys - -import ( - "syscall" - "time" -) - -// StatAtime returns the Atim -func StatAtime(st *syscall.Stat_t) syscall.Timespec { - return st.Atim -} - -// StatCtime returns the Ctim -func StatCtime(st *syscall.Stat_t) syscall.Timespec { - return st.Ctim -} - -// StatMtime returns the Mtim -func StatMtime(st *syscall.Stat_t) syscall.Timespec { - return st.Mtim -} - -// StatATimeAsTime returns st.Atim as a time.Time -func StatATimeAsTime(st *syscall.Stat_t) time.Time { - // The int64 conversions ensure the line compiles for 32-bit systems as well. - return time.Unix(int64(st.Atim.Sec), int64(st.Atim.Nsec)) // nolint: unconvert -} diff --git a/vendor/github.com/containerd/containerd/sys/stat_unix.go b/vendor/github.com/containerd/containerd/sys/stat_unix.go deleted file mode 100644 index 21a666dff..000000000 --- a/vendor/github.com/containerd/containerd/sys/stat_unix.go +++ /dev/null @@ -1,44 +0,0 @@ -// +build linux solaris - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package sys - -import ( - "syscall" - "time" -) - -// StatAtime returns the Atim -func StatAtime(st *syscall.Stat_t) syscall.Timespec { - return st.Atim -} - -// StatCtime returns the Ctim -func StatCtime(st *syscall.Stat_t) syscall.Timespec { - return st.Ctim -} - -// StatMtime returns the Mtim -func StatMtime(st *syscall.Stat_t) syscall.Timespec { - return st.Mtim -} - -// StatATimeAsTime returns st.Atim as a time.Time -func StatATimeAsTime(st *syscall.Stat_t) time.Time { - return time.Unix(int64(st.Atim.Sec), int64(st.Atim.Nsec)) // nolint: unconvert -} diff --git a/vendor/github.com/containerd/containerd/sys/subprocess_unsafe_linux.go b/vendor/github.com/containerd/containerd/sys/subprocess_unsafe_linux.go deleted file mode 100644 index 6e40a9c7d..000000000 --- a/vendor/github.com/containerd/containerd/sys/subprocess_unsafe_linux.go +++ /dev/null @@ -1,30 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package sys - -import ( - _ "unsafe" // required for go:linkname. -) - -//go:linkname beforeFork syscall.runtime_BeforeFork -func beforeFork() - -//go:linkname afterFork syscall.runtime_AfterFork -func afterFork() - -//go:linkname afterForkInChild syscall.runtime_AfterForkInChild -func afterForkInChild() diff --git a/vendor/github.com/containerd/containerd/sys/subprocess_unsafe_linux.s b/vendor/github.com/containerd/containerd/sys/subprocess_unsafe_linux.s deleted file mode 100644 index c073fa4ad..000000000 --- a/vendor/github.com/containerd/containerd/sys/subprocess_unsafe_linux.s +++ /dev/null @@ -1,15 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go b/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go index 708b26689..9ee97fc91 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go +++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go @@ -26,6 +26,7 @@ import ( "archive/tar" "bytes" "compress/gzip" + "errors" "fmt" "io" "io/ioutil" @@ -38,7 +39,6 @@ import ( "github.com/containerd/stargz-snapshotter/estargz/errorutil" "github.com/klauspost/compress/zstd" digest "github.com/opencontainers/go-digest" - "github.com/pkg/errors" "golang.org/x/sync/errgroup" ) @@ -142,7 +142,7 @@ func Build(tarBlob *io.SectionReader, opt ...Option) (_ *Blob, rErr error) { defer func() { if rErr != nil { if err := layerFiles.CleanupAll(); err != nil { - rErr = errors.Wrapf(rErr, "failed to cleanup tmp files: %v", err) + rErr = fmt.Errorf("failed to cleanup tmp files: %v: %w", err, rErr) } } }() @@ -307,7 +307,7 @@ func sortEntries(in io.ReaderAt, prioritized []string, missedPrioritized *[]stri // Import tar file. intar, err := importTar(in) if err != nil { - return nil, errors.Wrap(err, "failed to sort") + return nil, fmt.Errorf("failed to sort: %w", err) } // Sort the tar file respecting to the prioritized files list. @@ -318,7 +318,7 @@ func sortEntries(in io.ReaderAt, prioritized []string, missedPrioritized *[]stri *missedPrioritized = append(*missedPrioritized, l) continue // allow not found } - return nil, errors.Wrap(err, "failed to sort tar entries") + return nil, fmt.Errorf("failed to sort tar entries: %w", err) } } if len(prioritized) == 0 { @@ -371,7 +371,7 @@ func importTar(in io.ReaderAt) (*tarFile, error) { tf := &tarFile{} pw, err := newCountReader(in) if err != nil { - return nil, errors.Wrap(err, "failed to make position watcher") + return nil, fmt.Errorf("failed to make position watcher: %w", err) } tr := tar.NewReader(pw) @@ -383,7 +383,7 @@ func importTar(in io.ReaderAt) (*tarFile, error) { if err == io.EOF { break } else { - return nil, errors.Wrap(err, "failed to parse tar file") + return nil, fmt.Errorf("failed to parse tar file, %w", err) } } switch cleanEntryName(h.Name) { @@ -420,7 +420,7 @@ func moveRec(name string, in *tarFile, out *tarFile) error { _, okIn := in.get(name) _, okOut := out.get(name) if !okIn && !okOut { - return errors.Wrapf(errNotFound, "file: %q", name) + return fmt.Errorf("file: %q: %w", name, errNotFound) } parent, _ := path.Split(strings.TrimSuffix(name, "/")) diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go b/vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go index 2c36e89b4..4b655c145 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go +++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go @@ -27,6 +27,7 @@ import ( "bytes" "compress/gzip" "crypto/sha256" + "errors" "fmt" "hash" "io" @@ -40,7 +41,6 @@ import ( "github.com/containerd/stargz-snapshotter/estargz/errorutil" digest "github.com/opencontainers/go-digest" - "github.com/pkg/errors" "github.com/vbatts/tar-split/archive/tar" ) @@ -385,8 +385,7 @@ func (r *Reader) Verifiers() (TOCEntryVerifier, error) { if e.Digest != "" { d, err := digest.Parse(e.Digest) if err != nil { - return nil, errors.Wrapf(err, - "failed to parse regular file digest %q", e.Digest) + return nil, fmt.Errorf("failed to parse regular file digest %q: %w", e.Digest, err) } regDigestMap[e.Offset] = d } else { @@ -401,8 +400,7 @@ func (r *Reader) Verifiers() (TOCEntryVerifier, error) { if e.ChunkDigest != "" { d, err := digest.Parse(e.ChunkDigest) if err != nil { - return nil, errors.Wrapf(err, - "failed to parse chunk digest %q", e.ChunkDigest) + return nil, fmt.Errorf("failed to parse chunk digest %q: %w", e.ChunkDigest, err) } chunkDigestMap[e.Offset] = d } else { @@ -647,7 +645,7 @@ func Unpack(sr *io.SectionReader, c Decompressor) (io.ReadCloser, error) { } blobPayloadSize, _, _, err := c.ParseFooter(footer) if err != nil { - return nil, errors.Wrapf(err, "failed to parse footer") + return nil, fmt.Errorf("failed to parse footer: %w", err) } return c.Reader(io.LimitReader(sr, blobPayloadSize)) } diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/go.mod b/vendor/github.com/containerd/stargz-snapshotter/estargz/go.mod index b82879fd7..9256b36b9 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/estargz/go.mod +++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/go.mod @@ -3,9 +3,8 @@ module github.com/containerd/stargz-snapshotter/estargz go 1.16 require ( - github.com/klauspost/compress v1.14.2 + github.com/klauspost/compress v1.14.3 github.com/opencontainers/go-digest v1.0.0 - github.com/pkg/errors v0.9.1 github.com/vbatts/tar-split v0.11.2 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a ) diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/go.sum b/vendor/github.com/containerd/stargz-snapshotter/estargz/go.sum index 20433e16b..800028d92 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/estargz/go.sum +++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/go.sum @@ -1,12 +1,10 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw= -github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.14.3 h1:DQv1WP+iS4srNjibdnHtqu8JNWCDMluj5NzPnFJsnvk= +github.com/klauspost/compress v1.14.3/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -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/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/gzip.go b/vendor/github.com/containerd/stargz-snapshotter/estargz/gzip.go index 7330849cb..591d7a62e 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/estargz/gzip.go +++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/gzip.go @@ -34,7 +34,6 @@ import ( "strconv" digest "github.com/opencontainers/go-digest" - "github.com/pkg/errors" ) type gzipCompression struct { @@ -150,7 +149,7 @@ func (gz *GzipDecompressor) ParseFooter(p []byte) (blobPayloadSize, tocOffset, t } tocOffset, err = strconv.ParseInt(string(subfield[:16]), 16, 64) if err != nil { - return 0, 0, 0, errors.Wrapf(err, "legacy: failed to parse toc offset") + return 0, 0, 0, fmt.Errorf("legacy: failed to parse toc offset: %w", err) } return tocOffset, tocOffset, 0, nil } @@ -179,7 +178,7 @@ func (gz *LegacyGzipDecompressor) ParseFooter(p []byte) (blobPayloadSize, tocOff } zr, err := gzip.NewReader(bytes.NewReader(p)) if err != nil { - return 0, 0, 0, errors.Wrapf(err, "legacy: failed to get footer gzip reader") + return 0, 0, 0, fmt.Errorf("legacy: failed to get footer gzip reader: %w", err) } defer zr.Close() extra := zr.Header.Extra @@ -191,7 +190,7 @@ func (gz *LegacyGzipDecompressor) ParseFooter(p []byte) (blobPayloadSize, tocOff } tocOffset, err = strconv.ParseInt(string(extra[:16]), 16, 64) if err != nil { - return 0, 0, 0, errors.Wrapf(err, "legacy: failed to parse toc offset") + return 0, 0, 0, fmt.Errorf("legacy: failed to parse toc offset: %w", err) } return tocOffset, tocOffset, 0, nil } diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/testutil.go b/vendor/github.com/containerd/stargz-snapshotter/estargz/testutil.go index 9224e456d..1de13a470 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/estargz/testutil.go +++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/testutil.go @@ -28,6 +28,7 @@ import ( "compress/gzip" "crypto/sha256" "encoding/json" + "errors" "fmt" "io" "io/ioutil" @@ -41,7 +42,6 @@ import ( "github.com/containerd/stargz-snapshotter/estargz/errorutil" "github.com/klauspost/compress/zstd" digest "github.com/opencontainers/go-digest" - "github.com/pkg/errors" ) // TestingController is Compression with some helper methods necessary for testing. @@ -1062,18 +1062,18 @@ func parseStargz(sgz *io.SectionReader, controller TestingController) (decodedJT fSize := controller.FooterSize() footer := make([]byte, fSize) if _, err := sgz.ReadAt(footer, sgz.Size()-fSize); err != nil { - return nil, 0, errors.Wrap(err, "error reading footer") + return nil, 0, fmt.Errorf("error reading footer: %w", err) } _, tocOffset, _, err := controller.ParseFooter(footer[positive(int64(len(footer))-fSize):]) if err != nil { - return nil, 0, errors.Wrapf(err, "failed to parse footer") + return nil, 0, fmt.Errorf("failed to parse footer: %w", err) } // Decode the TOC JSON tocReader := io.NewSectionReader(sgz, tocOffset, sgz.Size()-tocOffset-fSize) decodedJTOC, _, err = controller.ParseTOC(tocReader) if err != nil { - return nil, 0, errors.Wrap(err, "failed to parse TOC") + return nil, 0, fmt.Errorf("failed to parse TOC: %w", err) } return decodedJTOC, tocOffset, nil } diff --git a/vendor/github.com/go-openapi/spec/.editorconfig b/vendor/github.com/go-openapi/spec/.editorconfig deleted file mode 100644 index 3152da69a..000000000 --- a/vendor/github.com/go-openapi/spec/.editorconfig +++ /dev/null @@ -1,26 +0,0 @@ -# top-most EditorConfig file -root = true - -# Unix-style newlines with a newline ending every file -[*] -end_of_line = lf -insert_final_newline = true -indent_style = space -indent_size = 2 -trim_trailing_whitespace = true - -# Set default charset -[*.{js,py,go,scala,rb,java,html,css,less,sass,md}] -charset = utf-8 - -# Tab indentation (no size specified) -[*.go] -indent_style = tab - -[*.md] -trim_trailing_whitespace = false - -# Matches the exact files either package.json or .travis.yml -[{package.json,.travis.yml}] -indent_style = space -indent_size = 2 diff --git a/vendor/github.com/go-openapi/spec/.gitignore b/vendor/github.com/go-openapi/spec/.gitignore deleted file mode 100644 index dd91ed6a0..000000000 --- a/vendor/github.com/go-openapi/spec/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -secrets.yml -coverage.out diff --git a/vendor/github.com/go-openapi/spec/.golangci.yml b/vendor/github.com/go-openapi/spec/.golangci.yml deleted file mode 100644 index 835d55e74..000000000 --- a/vendor/github.com/go-openapi/spec/.golangci.yml +++ /dev/null @@ -1,42 +0,0 @@ -linters-settings: - govet: - check-shadowing: true - golint: - min-confidence: 0 - gocyclo: - min-complexity: 45 - maligned: - suggest-new: true - dupl: - threshold: 200 - goconst: - min-len: 2 - min-occurrences: 2 - -linters: - enable-all: true - disable: - - maligned - - unparam - - lll - - gochecknoinits - - gochecknoglobals - - funlen - - godox - - gocognit - - whitespace - - wsl - - wrapcheck - - testpackage - - nlreturn - - gomnd - - exhaustivestruct - - goerr113 - - errorlint - - nestif - - godot - - gofumpt - - paralleltest - - tparallel - - thelper - - ifshort diff --git a/vendor/github.com/go-openapi/spec/.travis.yml b/vendor/github.com/go-openapi/spec/.travis.yml deleted file mode 100644 index 2281a07b0..000000000 --- a/vendor/github.com/go-openapi/spec/.travis.yml +++ /dev/null @@ -1,31 +0,0 @@ -after_success: -- bash <(curl -s https://codecov.io/bash) -go: -- 1.16.x -- 1.x -arch: - - amd64 -jobs: - include: - # only run fast tests on ppc64le - - go: 1.x - arch: ppc64le - script: - - gotestsum -f short-verbose -- ./... - - # include linting job, but only for latest go version and amd64 arch - - go: 1.x - arch: amd64 - install: - go get github.com/golangci/golangci-lint/cmd/golangci-lint - script: - - golangci-lint run --new-from-rev master - -install: -- GO111MODULE=off go get -u gotest.tools/gotestsum -language: go -notifications: - slack: - secure: QUWvCkBBK09GF7YtEvHHVt70JOkdlNBG0nIKu/5qc4/nW5HP8I2w0SEf/XR2je0eED1Qe3L/AfMCWwrEj+IUZc3l4v+ju8X8R3Lomhme0Eb0jd1MTMCuPcBT47YCj0M7RON7vXtbFfm1hFJ/jLe5+9FXz0hpXsR24PJc5ZIi/ogNwkaPqG4BmndzecpSh0vc2FJPZUD9LT0I09REY/vXR0oQAalLkW0asGD5taHZTUZq/kBpsNxaAFrLM23i4mUcf33M5fjLpvx5LRICrX/57XpBrDh2TooBU6Qj3CgoY0uPRYUmSNxbVx1czNzl2JtEpb5yjoxfVPQeg0BvQM00G8LJINISR+ohrjhkZmAqchDupAX+yFrxTtORa78CtnIL6z/aTNlgwwVD8kvL/1pFA/JWYmKDmz93mV/+6wubGzNSQCstzjkFA4/iZEKewKUoRIAi/fxyscP6L/rCpmY/4llZZvrnyTqVbt6URWpopUpH4rwYqreXAtJxJsfBJIeSmUIiDIOMGkCTvyTEW3fWGmGoqWtSHLoaWDyAIGb7azb+KvfpWtEcoPFWfSWU+LGee0A/YsUhBl7ADB9A0CJEuR8q4BPpKpfLwPKSiKSAXL7zDkyjExyhtgqbSl2jS+rKIHOZNL8JkCcTP2MKMVd563C5rC5FMKqu3S9m2b6380E= -script: -- gotestsum -f short-verbose -- -race -coverprofile=coverage.txt -covermode=atomic ./... diff --git a/vendor/github.com/go-openapi/spec/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/spec/CODE_OF_CONDUCT.md deleted file mode 100644 index 9322b065e..000000000 --- a/vendor/github.com/go-openapi/spec/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,74 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of experience, -nationality, personal appearance, race, religion, or sexual identity and -orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or -advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at ivan+abuse@flanders.co.nz. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at [http://contributor-covenant.org/version/1/4][version] - -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ diff --git a/vendor/github.com/go-openapi/spec/README.md b/vendor/github.com/go-openapi/spec/README.md deleted file mode 100644 index 18782c6da..000000000 --- a/vendor/github.com/go-openapi/spec/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# OAI object model - -[![Build Status](https://travis-ci.org/go-openapi/spec.svg?branch=master)](https://travis-ci.org/go-openapi/spec) - -[![codecov](https://codecov.io/gh/go-openapi/spec/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/spec) -[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io) -[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/spec/master/LICENSE) -[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/spec.svg)](https://pkg.go.dev/github.com/go-openapi/spec) -[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/spec)](https://goreportcard.com/report/github.com/go-openapi/spec) - -The object model for OpenAPI specification documents. - -### FAQ - -* What does this do? - -> 1. This package knows how to marshal and unmarshal Swagger API specifications into a golang object model -> 2. It knows how to resolve $ref and expand them to make a single root document - -* How does it play with the rest of the go-openapi packages ? - -> 1. This package is at the core of the go-openapi suite of packages and [code generator](https://github.com/go-swagger/go-swagger) -> 2. There is a [spec loading package](https://github.com/go-openapi/loads) to fetch specs as JSON or YAML from local or remote locations -> 3. There is a [spec validation package](https://github.com/go-openapi/validate) built on top of it -> 4. There is a [spec analysis package](https://github.com/go-openapi/analysis) built on top of it, to analyze, flatten, fix and merge spec documents - -* Does this library support OpenAPI 3? - -> No. -> This package currently only supports OpenAPI 2.0 (aka Swagger 2.0). -> There is no plan to make it evolve toward supporting OpenAPI 3.x. -> This [discussion thread](https://github.com/go-openapi/spec/issues/21) relates the full story. -> -> An early attempt to support Swagger 3 may be found at: https://github.com/go-openapi/spec3 diff --git a/vendor/github.com/go-openapi/spec/appveyor.yml b/vendor/github.com/go-openapi/spec/appveyor.yml deleted file mode 100644 index 090359391..000000000 --- a/vendor/github.com/go-openapi/spec/appveyor.yml +++ /dev/null @@ -1,32 +0,0 @@ -version: "0.1.{build}" - -clone_folder: C:\go-openapi\spec -shallow_clone: true # for startup speed -pull_requests: - do_not_increment_build_number: true - -#skip_tags: true -#skip_branch_with_pr: true - -# appveyor.yml -build: off - -environment: - GOPATH: c:\gopath - -stack: go 1.15 - -test_script: - - go test -v -timeout 20m ./... - -deploy: off - -notifications: - - provider: Slack - incoming_webhook: https://hooks.slack.com/services/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 - auth_token: - secure: Sf7kZf7ZGbnwWUMpffHwMu5A0cHkLK2MYY32LNTPj4+/3qC3Ghl7+9v4TSLOqOlCwdRNjOGblAq7s+GDJed6/xgRQl1JtCi1klzZNrYX4q01pgTPvvGcwbBkIYgeMaPeIRcK9OZnud7sRXdttozgTOpytps2U6Js32ip7uj5mHSg2ub0FwoSJwlS6dbezZ8+eDhoha0F/guY99BEwx8Bd+zROrT2TFGsSGOFGN6wFc7moCqTHO/YkWib13a2QNXqOxCCVBy/lt76Wp+JkeFppjHlzs/2lP3EAk13RIUAaesdEUHvIHrzCyNJEd3/+KO2DzsWOYfpktd+KBCvgaYOsoo7ubdT3IROeAegZdCgo/6xgCEsmFc9ZcqCfN5yNx2A+BZ2Vwmpws+bQ1E1+B5HDzzaiLcYfG4X2O210QVGVDLWsv1jqD+uPYeHY2WRfh5ZsIUFvaqgUEnwHwrK44/8REAhQavt1QAj5uJpsRd7CkRVPWRNK+yIky+wgbVUFEchRNmS55E7QWf+W4+4QZkQi7vUTMc9nbTUu2Es9NfvfudOpM2wZbn98fjpb/qq/nRv6Bk+ca+7XD5/IgNLMbWp2ouDdzbiHLCOfDUiHiDJhLfFZx9Bwo7ZwfzeOlbrQX66bx7xRKYmOe4DLrXhNcpbsMa8qbfxlZRCmYbubB/Y8h4= - channel: bots - on_build_success: false - on_build_failure: true - on_build_status_changed: true diff --git a/vendor/github.com/go-openapi/spec/bindata.go b/vendor/github.com/go-openapi/spec/bindata.go deleted file mode 100644 index afc83850c..000000000 --- a/vendor/github.com/go-openapi/spec/bindata.go +++ /dev/null @@ -1,297 +0,0 @@ -// Code generated by go-bindata. DO NOT EDIT. -// sources: -// schemas/jsonschema-draft-04.json (4.357kB) -// schemas/v2/schema.json (40.248kB) - -package spec - -import ( - "bytes" - "compress/gzip" - "crypto/sha256" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - "time" -) - -func bindataRead(data []byte, name string) ([]byte, error) { - gz, err := gzip.NewReader(bytes.NewBuffer(data)) - if err != nil { - return nil, fmt.Errorf("read %q: %v", name, err) - } - - var buf bytes.Buffer - _, err = io.Copy(&buf, gz) - clErr := gz.Close() - - if err != nil { - return nil, fmt.Errorf("read %q: %v", name, err) - } - if clErr != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -type asset struct { - bytes []byte - info os.FileInfo - digest [sha256.Size]byte -} - -type bindataFileInfo struct { - name string - size int64 - mode os.FileMode - modTime time.Time -} - -func (fi bindataFileInfo) Name() string { - return fi.name -} -func (fi bindataFileInfo) Size() int64 { - return fi.size -} -func (fi bindataFileInfo) Mode() os.FileMode { - return fi.mode -} -func (fi bindataFileInfo) ModTime() time.Time { - return fi.modTime -} -func (fi bindataFileInfo) IsDir() bool { - return false -} -func (fi bindataFileInfo) Sys() interface{} { - return nil -} - -var _jsonschemaDraft04Json = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x57\x3d\x6f\xdb\x3c\x10\xde\xf3\x2b\x08\x26\x63\xf2\x2a\x2f\xd0\xc9\x5b\xd1\x2e\x01\x5a\x34\x43\x37\x23\x03\x6d\x9d\x6c\x06\x14\xa9\x50\x54\x60\xc3\xd0\x7f\x2f\x28\x4a\x14\x29\x91\x92\x2d\xa7\x8d\x97\x28\xbc\xaf\xe7\x8e\xf7\xc5\xd3\x0d\x42\x08\x61\x9a\xe2\x15\xc2\x7b\xa5\x8a\x55\x92\xbc\x96\x82\x3f\x94\xdb\x3d\xe4\xe4\x3f\x21\x77\x49\x2a\x49\xa6\x1e\x1e\xbf\x24\xe6\xec\x16\xdf\x1b\xa1\x3b\xf3\xff\x02\xc9\x14\xca\xad\xa4\x85\xa2\x82\x6b\xe9\x6f\x42\x02\x32\x2c\x28\x07\x45\x5a\x15\x3d\x77\x46\x39\xd5\xcc\x25\x5e\x21\x83\xb8\x21\x18\xb6\xaf\x52\x92\xa3\x47\x68\x88\xea\x58\x80\x56\x4e\x1a\xf2\xbd\x4f\xcc\x29\x7f\x52\x90\x6b\x7d\xff\x0f\x48\xb4\x3d\x3f\x21\x7c\x27\x21\xd3\x2a\x6e\x31\xaa\x2d\x53\xdd\xf3\xe3\x42\x94\x54\xd1\x77\x78\xe2\x0a\x76\x20\xe3\x20\x68\xcb\x30\x86\x41\xf3\x2a\xc7\x2b\xf4\x78\x8e\xfe\xef\x90\x91\x8a\xa9\xc7\xb1\x1d\xc2\xd8\x2f\x0d\x75\xed\xc1\x4e\x9c\xc8\x25\x43\xac\xa8\xbe\xd7\xcc\xa9\xd1\xa9\x21\xa0\x1a\xbd\x04\x61\x94\x34\x2f\x18\xfc\x3e\x16\x50\x8e\x4d\x03\x6f\x1c\x58\xdb\x48\x23\xbc\x11\x82\x01\xe1\xfa\xd3\x3a\x8e\x30\xaf\x18\x33\x7f\xf3\x8d\x39\x11\x9b\x57\xd8\x2a\xfd\x55\x2a\x49\xf9\x0e\xc7\xec\x37\xd4\x25\xf7\xec\x5c\x66\xc7\xd7\x99\xaa\xcf\x4f\x89\x8a\xd3\xb7\x0a\x3a\xaa\x92\x15\xf4\x30\x6f\x1c\xb0\xd6\x46\xe7\x98\x39\x2d\xa4\x28\x40\x2a\x3a\x88\x9e\x29\xba\x88\x37\x2d\xca\x60\x38\xfa\xba\x5b\x20\xac\xa8\x62\xb0\x4c\xd4\xaf\xda\x45\x0a\xba\x5c\x3b\xb9\xc7\x79\xc5\x14\x2d\x18\x34\x19\x1c\x51\xdb\x25\x4d\xb4\x7e\x06\x14\x38\x6c\x59\x55\xd2\x77\xf8\x69\x59\xfc\x7b\x73\xed\x93\x43\xcb\x32\x6d\x3c\x28\xdc\x1b\x9a\xd3\x62\xab\xc2\x27\xf7\x41\xc9\x08\x2b\x23\x08\xad\x13\x57\x21\x9c\xd3\x72\x0d\x42\x72\xf8\x01\x7c\xa7\xf6\x83\xce\x39\xd7\x82\x3c\x1f\x2f\xd6\x60\x1b\xa2\xdf\x35\x89\x52\x20\xe7\x73\x74\xe0\x66\x26\x64\x4e\xb4\x97\x58\xc2\x0e\x0e\xe1\x60\x92\x34\x6d\xa0\x10\xd6\xb5\x83\x61\x27\xe6\x47\xd3\x89\xbd\x63\xfd\x3b\x8d\x03\x3d\x6c\x42\x2d\x5b\x70\xee\xe8\xdf\x4b\xf4\x66\x4e\xe1\x01\x45\x17\x80\x74\xad\x4f\xc3\xf3\xae\xc6\x1d\xc6\xd7\xc2\xce\xc9\xe1\x29\x30\x86\x2f\x4a\xa6\x4b\x15\x84\x73\xc9\x6f\xfd\x7f\xa5\x6e\x9e\xbd\xf1\xb0\xd4\xdd\x45\x5a\xc2\x3e\x4b\x78\xab\xa8\x84\x74\x4a\x91\x3b\x92\x23\x05\xf2\x1c\x1e\x7b\xf3\x09\xf8\xcf\xab\x24\xb6\x60\xa2\xe8\x4c\x9f\x75\x77\xaa\x8c\xe6\x01\x45\x36\x86\xcf\xc3\x63\x3a\xea\xd4\x8d\x7e\x06\xac\x14\x0a\xe0\x29\xf0\xed\x07\x22\x1a\x65\xda\x44\xae\xa2\x73\x1a\xe6\x90\x69\xa2\x8c\x46\xb2\x2f\xde\x49\x38\x08\xed\xfe\xfd\x41\xaf\x9f\xa9\x55\xd7\xdd\x22\x8d\xfa\x45\x63\xc5\x0f\x80\xf3\xb4\x08\xd6\x79\x30\x9e\x93\xee\x59\xa6\xd0\x4b\xee\x22\xe3\x33\xc1\x3a\x27\x68\x36\x78\x7e\x87\x0a\x06\xd5\x2e\x20\xd3\xaf\x15\xfb\xd8\x3b\x73\x14\xbb\x92\xed\x05\x5d\x2e\x29\x38\x2c\x94\xe4\x42\x45\x5e\xd3\xb5\x7d\xdf\x47\xca\x38\xb4\x5c\xaf\xfb\x7d\xdd\x6d\xf4\xa1\x2d\x77\xdd\x2f\xce\x6d\xc4\x7b\x8b\x4e\x67\xa9\x6f\xfe\x04\x00\x00\xff\xff\xb1\xd1\x27\x78\x05\x11\x00\x00") - -func jsonschemaDraft04JsonBytes() ([]byte, error) { - return bindataRead( - _jsonschemaDraft04Json, - "jsonschema-draft-04.json", - ) -} - -func jsonschemaDraft04Json() (*asset, error) { - bytes, err := jsonschemaDraft04JsonBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "jsonschema-draft-04.json", size: 4357, mode: os.FileMode(0640), modTime: time.Unix(1568963823, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe1, 0x48, 0x9d, 0xb, 0x47, 0x55, 0xf0, 0x27, 0x93, 0x30, 0x25, 0x91, 0xd3, 0xfc, 0xb8, 0xf0, 0x7b, 0x68, 0x93, 0xa8, 0x2a, 0x94, 0xf2, 0x48, 0x95, 0xf8, 0xe4, 0xed, 0xf1, 0x1b, 0x82, 0xe2}} - return a, nil -} - -var _v2SchemaJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5d\x4f\x93\xdb\x36\xb2\xbf\xfb\x53\xa0\x14\x57\xd9\xae\xd8\x92\xe3\xf7\x2e\xcf\x97\xd4\xbc\xd8\x49\x66\x37\x5e\x4f\x79\x26\xbb\x87\x78\x5c\x05\x91\x2d\x09\x09\x09\x30\x00\x38\x33\x5a\xef\x7c\xf7\x2d\xf0\x9f\x08\x02\x20\x41\x8a\xd2\xc8\x0e\x0f\xa9\x78\x28\xa0\xd1\xdd\x68\x34\x7e\xdd\xf8\xf7\xf9\x11\x42\x33\x49\x64\x04\xb3\xd7\x68\x76\x86\xfe\x76\xf9\xfe\x1f\xe8\x32\xd8\x40\x8c\xd1\x8a\x71\x74\x79\x8b\xd7\x6b\xe0\xe8\xd5\xfc\x25\x3a\xbb\x38\x9f\xcf\x9e\xab\x0a\x24\x54\xa5\x37\x52\x26\xaf\x17\x0b\x91\x17\x99\x13\xb6\xb8\x79\xb5\x10\x59\xdd\xf9\xef\x82\xd1\x6f\xf2\xc2\x8f\xf3\x4f\xb5\x1a\xea\xc7\x17\x45\x41\xc6\xd7\x8b\x90\xe3\x95\x7c\xf1\xf2\x7f\x8b\xca\x45\x3d\xb9\x4d\x32\xa6\xd8\xf2\x77\x08\x64\xfe\x8d\xc3\x9f\x29\xe1\xa0\x9a\xff\xed\x11\x42\x08\xcd\x8a\xd6\xb3\x9f\x15\x67\x74\xc5\xca\x7f\x27\x58\x6e\xc4\xec\x11\x42\xd7\x59\x5d\x1c\x86\x44\x12\x46\x71\x74\xc1\x59\x02\x5c\x12\x10\xb3\xd7\x68\x85\x23\x01\x59\x81\x04\x4b\x09\x9c\x6a\xbf\x7e\xce\x49\x7d\xba\x7b\x51\xfd\xa1\x44\xe2\xb0\x52\xac\x7d\xb3\x08\x61\x45\x68\x46\x56\x2c\x6e\x80\x86\x8c\xbf\xbd\x93\x40\x05\x61\x74\x96\x95\xbe\x7f\x84\xd0\x7d\x4e\xde\x42\xb7\xe4\xbe\x46\xbb\x14\x5b\x48\x4e\xe8\xba\x90\x05\xa1\x19\xd0\x34\xae\xc4\xce\xbe\xbc\x9a\xbf\x9c\x15\x7f\x5d\x57\xc5\x42\x10\x01\x27\x89\xe2\x48\x51\xb9\xda\x40\xd5\x87\x37\xc0\x15\x5f\x88\xad\x90\xdc\x10\x81\x42\x16\xa4\x31\x50\x39\x2f\x38\xad\xab\xb0\x53\xd8\xac\x94\x56\x6f\xc3\x84\xf4\x11\xa4\x50\xb3\xfa\xe9\xd3\x6f\x9f\x3e\xdf\x2f\xd0\xeb\x8f\x1f\x3f\x7e\xbc\xfe\xf6\xe9\xf7\xaf\x5f\x7f\xfc\x18\x7e\xfb\xec\xfb\xc7\xb3\x36\x79\x54\x43\xe8\x29\xc5\x31\x20\xc6\x11\x49\x9e\xe5\x12\x41\x66\xa0\xe8\xed\x1d\x8e\x93\x08\x5e\xa3\x27\x3b\xc3\x7c\xa2\x73\xba\xc4\x02\x2e\xb0\xdc\xf4\xe5\x76\xd1\xca\x96\xa2\x8a\x94\xcd\x21\xc9\x6c\xec\x2c\x70\x42\x9e\x34\x74\x9d\x19\x7c\xcd\x20\x9c\xea\x2e\x0a\xfe\x42\x84\xd4\x29\x04\x8c\x8a\xb4\x41\xa2\xc1\xdc\x19\x8a\x88\x90\x4a\x49\xef\xce\xdf\xbd\x45\x4a\x52\x81\x70\x10\x40\x22\x21\x44\xcb\x6d\xc5\xec\x4e\x3c\x1c\x45\xef\x57\x9a\xb5\x7d\xae\xfe\xe5\xe4\x31\x86\x90\xe0\xab\x6d\x02\x3b\x2e\xcb\x11\x90\xd9\xa8\xc6\x77\xc2\x59\x98\x06\xfd\xf9\x2e\x78\x45\x01\xa6\xa8\xa0\x71\x5c\xbe\x33\xa7\xd2\xd9\x5f\x95\xef\xd9\xd5\xac\xfd\xdc\x5d\xbf\x5e\xb8\xd1\x3e\xc7\x31\x48\xe0\x5e\x4c\x14\x65\xdf\xb8\xa8\x71\x10\x09\xa3\xc2\xc7\x02\xcb\xa2\x4e\x5a\x02\x82\x94\x13\xb9\xf5\x30\xe6\xb2\xa4\xb5\xfe\x9b\x3e\x7a\xb2\x55\xd2\xa8\x4a\xbc\x16\xb6\x71\x8e\x39\xc7\xdb\x9d\xe1\x10\x09\x71\xbd\x9c\xb3\x41\x89\xd7\xa5\x89\xdc\x57\xb5\x53\x4a\xfe\x4c\xe1\xbc\xa0\x21\x79\x0a\x1a\x0f\x70\xa7\x5c\x08\x8e\xde\xb0\xc0\x43\x24\xad\x74\x63\x0e\xb1\xd9\x90\xe1\xb0\x2d\x13\xa7\x6d\x78\xfd\x04\x14\x38\x8e\x90\xaa\xce\x63\xac\x3e\x23\xbc\x64\xa9\xb4\xf8\x03\x63\xde\xcd\xbe\x16\x13\x4a\x55\xac\x82\x12\xc6\xac\xd4\x35\xf7\x22\xd4\x3a\xff\x22\x73\x0e\x6e\x51\xa0\x75\x1e\xae\x8f\xe8\x5d\xc7\x59\xe6\xe4\x9a\x18\x8d\xd6\x1c\x53\x84\x4d\xb7\x67\x28\x37\x09\x84\x69\x88\x12\x0e\x01\x11\x80\x32\xa2\xf5\xb9\xaa\xc6\xd9\x73\x53\xab\xfb\xb4\x2e\x20\xc6\x54\x92\xa0\x9a\xf3\x69\x1a\x2f\x81\x77\x37\xae\x53\x1a\xce\x40\xc4\xa8\x82\x1c\xb5\xef\xda\x24\x7d\xb9\x61\x69\x14\xa2\x25\xa0\x90\xac\x56\xc0\x81\x4a\xb4\xe2\x2c\xce\x4a\x64\x7a\x9a\x23\xf4\x13\x91\x3f\xa7\x4b\xf4\x63\x84\x6f\x18\x87\x10\xbd\xc3\xfc\x8f\x90\xdd\x52\x44\x04\xc2\x51\xc4\x6e\x21\x74\x48\x21\x81\xc7\xe2\xfd\xea\x12\xf8\x0d\x09\xf6\xe9\x47\x35\xaf\x67\xc4\x14\xf7\x22\x27\x97\xe1\xe2\x76\x2d\x06\x8c\x4a\x1c\x48\x3f\x73\x2d\x0b\x5b\x29\x45\x24\x00\x2a\x0c\x11\xec\x94\xca\xc2\xa6\xc1\x37\x21\x43\x83\x3b\x5f\x97\xf1\x43\x5e\x53\x73\x19\xa5\x36\xd8\x2d\x05\x2e\x34\x0b\xeb\x39\xfc\x1d\x63\x51\x01\xbd\x3d\xbb\x90\x84\x40\x25\x59\x6d\x09\x5d\xa3\x1c\x37\xe6\x5c\x16\x9a\x40\x09\x70\xc1\xe8\x82\xf1\x35\xa6\xe4\xdf\x99\x5c\x8e\x9e\x4d\x79\xb4\x27\x2f\xbf\x7e\xf8\x05\x25\x8c\x50\xa9\x98\x29\x90\x62\x60\xea\x75\xae\x13\xca\xbf\x2b\x1a\x29\x27\x76\xd6\x20\xc6\x64\x5f\xe6\x32\x1a\x08\x87\x21\x07\x21\xbc\xb4\xe4\xe0\x32\x67\xa6\xcd\xf3\x1e\xcd\xd9\x6b\xb6\x6f\x8e\x27\xa7\xed\xdb\xe7\xbc\xcc\x1a\x07\xce\x6f\x87\x33\xf0\xba\x51\x17\x22\x66\x78\x79\x8e\xce\xe5\x13\x81\x80\x06\x2c\xe5\x78\x0d\xa1\xb2\xb8\x54\xa8\x79\x09\xbd\xbf\x3c\x47\x01\x8b\x13\x2c\xc9\x32\xaa\xaa\x1d\xd5\xee\xab\x36\xbd\x6c\xfd\x54\x6c\xc8\x08\x01\x3c\xbd\xe7\x07\x88\xb0\x24\x37\x79\x90\x28\x4a\x1d\x10\x1a\x92\x1b\x12\xa6\x38\x42\x40\xc3\x4c\x43\x62\x8e\xae\x36\xb0\x45\x71\x2a\xa4\x9a\x23\x79\x59\xb1\xa8\xf2\xa4\x0c\x60\x9f\xcc\x8d\x40\xf5\x80\xca\xa8\x99\xc3\xa7\x85\x1f\x31\x25\xa9\x82\xc5\x6d\xbd\xd8\x36\x76\x7c\x02\x28\x97\xf6\x1d\x74\x3b\x11\x7e\x91\xae\x32\xf8\x6c\xf4\xe6\x7b\x9a\xa5\x1f\x62\xc6\x21\xcf\x9a\xe5\xed\x8b\x02\xf3\x2c\x33\x33\xdf\x00\xca\xc9\x09\xb4\x04\xf5\xa5\x08\xd7\xc3\x02\x18\x66\xf1\xab\x1e\x83\x37\x4c\xcd\x12\xc1\x1d\x50\xf6\xaa\xbd\xfe\xe2\x73\x48\x38\x08\xa0\x32\x9b\x18\x44\x86\x0b\x6a\xc1\xaa\x26\x96\x2d\x96\x3c\xa0\x54\x65\x73\xe3\x08\xb5\x8b\x99\xbd\x82\xbc\x9e\xc2\xe8\x53\x46\x83\x3f\x33\x54\x2b\x5b\xad\x92\x79\xd9\x8f\x5d\x93\x98\xf2\xe6\xc6\x1c\xe6\x9a\x9e\xfc\x43\x82\x31\x66\x8e\x53\x77\xfe\x90\xe7\xf3\xf6\xe9\x62\x23\x3f\x10\x93\x18\xae\x72\x1a\x9d\xf9\x48\xcb\xcc\x5a\x65\xc7\x4a\x04\xf0\xf3\xd5\xd5\x05\x8a\x41\x08\xbc\x86\x86\x43\x51\x6c\xe0\x46\x57\xf6\x44\x40\x0d\xfb\xff\xa2\xc3\x7c\x3d\x39\x84\xdc\x09\x22\x64\x4f\x12\xd9\xba\xaa\xf6\xe3\xbd\x56\xdd\x91\x25\x6a\x14\x9c\x89\x34\x8e\x31\xdf\xee\x15\x7e\x2f\x39\x81\x15\x2a\x28\x95\x66\x51\xf5\xfd\x83\xc5\xfe\x15\x07\xcf\xf7\x08\xee\x1d\x8e\xb6\xc5\x52\xcc\x8c\x5a\x93\x66\xc5\xd8\x79\x38\x46\xd6\xa7\x88\x37\xc9\x2e\xe3\xd2\xa5\x7b\x4b\x3a\xdc\xa1\xdc\x9e\x29\xf1\x8c\x8a\x99\x16\x47\x8d\xd4\x78\x8b\xf6\x1c\xe9\x71\x54\x1b\x69\xa8\x4a\x93\x37\xe5\xb2\x2c\x4f\x0c\x92\xab\xa0\x73\x32\x72\x59\xd3\xf0\x2d\x8d\xed\xca\x37\x16\x19\x9e\xdb\x1c\xab\x17\x49\xc3\x0f\x37\xdc\x88\xb1\xb4\xd4\x42\xcb\x58\x5e\x6a\x52\x0b\x15\x10\x0a\xb0\x04\xe7\xf8\x58\x32\x16\x01\xa6\xcd\x01\xb2\xc2\x69\x24\x35\x38\x6f\x30\x6a\xae\x1b\xb4\x71\xaa\xad\x1d\xa0\xd6\x20\x2d\x8b\x3c\xc6\x82\x62\x27\x34\x6d\x15\x84\x7b\x43\xb1\x35\x78\xa6\x24\x77\x28\xc1\x6e\xfc\xe9\x48\x74\xf4\x15\xe3\xe1\x84\x42\x88\x40\x7a\x26\x49\x3b\x48\xb1\xa4\x19\x8e\x0c\xa7\xb5\x01\x6c\x0c\x97\x61\x8a\xc2\x32\xd8\x8c\x44\x69\x24\xbf\x65\x1d\x74\xd6\xe5\x44\xef\xec\x48\x5e\xb7\x8a\xa3\x29\x8e\x41\x64\xce\x1f\x88\xdc\x00\x47\x4b\x40\x98\x6e\xd1\x0d\x8e\x48\x98\x63\x5c\x21\xb1\x4c\x05\x0a\x58\x98\xc5\x6d\x4f\x0a\x77\x53\x4f\x8b\xc4\x44\x1f\xb2\xdf\x8d\x3b\xea\x9f\xfe\xf6\xf2\xc5\xff\x5d\x7f\xfe\x9f\xfb\x67\x8f\xff\xf3\xe9\x69\xd1\xfe\xb3\xc7\xfd\x3c\xf8\x3f\x71\x94\x82\x23\xd1\x72\x00\xb7\x42\x99\x6c\xc0\x60\x7b\x0f\x79\xea\xa8\x53\x4b\x56\x31\xfa\x0b\x52\x9f\x96\xdb\xcd\x2f\xd7\x67\xcd\x04\x19\x85\xfe\xdb\x02\x9a\x59\x03\xad\x63\x3c\xea\xff\x2e\x18\xfd\x00\xd9\xe2\x56\x60\x59\x93\xb9\xb6\xb2\x3e\x3c\x2c\xab\x0f\xa7\xb2\x89\x43\xc7\xf6\xd5\xce\x2e\xad\xa6\xa9\xed\xa6\xc6\x5a\xb4\xa6\x67\xdf\x8c\x26\x7b\x50\x5a\x91\x08\x2e\x6d\xd4\x3a\xc1\x9d\xf2\xdb\xde\x1e\xb2\x2c\x6c\xa5\x64\xc9\x16\xb4\x90\xaa\x4a\xb7\x0c\xde\x13\xc3\x2a\x9a\x11\x9b\x7a\x1b\x3d\x95\x97\x37\x31\x6b\x69\x7e\x34\xc0\x67\x1f\x66\x19\x49\xef\xf1\x25\xf5\xac\x0e\xea\x0a\x28\x8d\x4d\x7e\xd9\x57\x4b\x49\xe5\xc6\xb3\x25\xfd\xe6\x57\x42\x25\xac\xcd\xcf\x36\x74\x8e\xca\x24\x47\xe7\x80\xa8\x92\x72\xbd\x3d\x84\x2d\x65\xe2\x82\x1a\x9c\xc4\x44\x92\x1b\x10\x79\x8a\xc4\x4a\x2f\x60\x51\x04\x81\xaa\xf0\xa3\x95\x27\xd7\x12\x7b\xa3\x96\x03\x45\x96\xc1\x8a\x07\xc9\xb2\xb0\x95\x52\x8c\xef\x48\x9c\xc6\x7e\x94\xca\xc2\x0e\x07\x12\x44\xa9\x20\x37\xf0\xae\x0f\x49\xa3\x96\x9d\x4b\x42\x7b\x70\x59\x14\xee\xe0\xb2\x0f\x49\xa3\x96\x4b\x97\xbf\x00\x5d\x4b\x4f\xfc\xbb\x2b\xee\x92\xb9\x17\xb5\xaa\xb8\x0b\x97\x17\x9b\x43\xfd\xd6\xc2\xb2\xc2\x2e\x29\xcf\xfd\x87\x4a\x55\xda\x25\x63\x1f\x5a\x65\x69\x2b\x2d\x3d\x67\xe9\x41\xae\x5e\xc1\x6e\x2b\xd4\xdb\x3e\xa8\xd3\x26\xd2\x48\x92\x24\xca\x61\x86\x8f\x8c\xbb\xf2\x8e\x91\xdf\x1f\x06\x19\x33\xf3\x03\x4d\xba\xcd\xe2\x2d\xfb\x69\xe9\x16\x15\x13\xd5\x56\x85\x4e\x3c\x5b\x8a\xbf\x25\x72\x83\xee\x5e\x20\x22\xf2\xc8\xaa\x7b\xdb\x8e\xe4\x29\x58\xca\x38\xb7\x3f\x2e\x59\xb8\xbd\xa8\x16\x16\xf7\xdb\x79\x51\x9f\x5a\xb4\x8d\x87\x3a\x6e\xbc\x3e\xc5\xb4\xcd\x58\xf9\xf5\x3c\xb9\x6f\x49\xaf\x57\xc1\xfa\x1c\x5d\x6d\x88\x8a\x8b\xd3\x28\xcc\xb7\xef\x10\x8a\x4a\x74\xa9\x4a\xa7\x62\xbf\x0d\x76\x23\x6f\x59\xd9\x31\xee\x40\x11\xfb\x28\xec\x8d\x22\x1c\x13\x5a\x64\x94\x23\x16\x60\xbb\xd2\x7c\xa0\x98\xb2\xe5\x6e\xbc\x54\x33\xe0\x3e\xb9\x52\x17\xdb\xb7\x1b\xc8\x12\x20\x8c\x23\xca\x64\x7e\x78\xa3\x62\x5b\x75\x56\xd9\x9e\x2a\x91\x27\xb0\x70\x34\x1f\x90\x89\xb5\x86\x73\x7e\x71\xda\x1e\xfb\x3a\x72\xdc\x5e\x79\x88\xcb\x74\x79\xd9\x64\xe4\xd4\xc2\x9e\xce\xb1\xfe\x85\x5a\xc0\xe9\x0c\x34\x3d\xd0\x43\xce\xa1\x36\x39\xd5\xa1\x4e\xf5\xf8\xb1\xa9\x23\x08\x75\x84\xac\x53\x6c\x3a\xc5\xa6\x53\x6c\x3a\xc5\xa6\x7f\xc5\xd8\xf4\x51\xfd\xff\x25\x4e\xfa\x33\x05\xbe\x9d\x60\xd2\x04\x93\x6a\x5f\x33\x9b\x98\x50\xd2\xe1\x50\x52\xc6\xcc\xdb\x38\x91\xdb\xe6\xaa\xa2\x8f\xa1\x6a\xa6\xd4\xc6\x56\xd6\x8c\x40\x02\x68\x48\xe8\x1a\xe1\x9a\xd9\x2e\xb7\x05\xc3\x34\xda\x2a\xbb\xcd\x12\x36\x98\x22\x50\x4c\xa1\x1b\xc5\xd5\x84\xf0\xbe\x24\x84\xf7\x2f\x22\x37\xef\x94\xd7\x9f\xa0\xde\x04\xf5\x26\xa8\x37\x41\x3d\x64\x40\x3d\xe5\xf2\xde\x60\x89\x27\xb4\x37\xa1\xbd\xda\xd7\xd2\x2c\x26\xc0\x37\x01\x3e\x1b\xef\x5f\x06\xe0\x6b\x7c\x5c\x91\x08\x26\x10\x38\x81\xc0\x09\x04\x76\x4a\x3d\x81\xc0\xbf\x12\x08\x4c\xb0\xdc\x7c\x99\x00\xd0\x75\x70\xb4\xf8\x5a\x7c\xea\xde\x3e\x39\x08\x30\x5a\x27\x35\xed\xb4\x65\xad\x69\x74\x10\x88\x79\xe2\x30\x52\x19\xd6\x04\x21\xa7\x95\xd5\x0e\x03\xf8\xda\x20\xd7\x84\xb4\x26\xa4\x35\x21\xad\x09\x69\x21\x03\x69\x51\x46\xff\xff\x18\x9b\x54\xed\x87\x47\x06\x9d\x4e\x73\x6e\x9a\xb3\xa9\xce\x83\x5e\x4b\xc6\x71\x20\x45\xd7\x72\xf5\x40\x72\x0e\x34\x6c\xf4\x6c\xf3\xba\x5e\x4b\x97\x0e\x52\xb8\xbe\x8b\x79\xa0\x10\x86\xa1\x75\xb0\x6f\xec\xc8\xf4\x3d\x4d\x7b\x86\xc2\x02\x31\x12\x51\xbf\x07\x94\xad\x10\xd6\x2e\x79\xcf\xe9\x1c\xf5\x1e\x31\x23\x5c\x18\xfb\x9c\xfb\x70\xe0\x62\xbd\xf7\xb5\x94\xcf\xf3\xf6\xfa\xc5\x4e\x9c\x85\x76\x1d\xae\x37\xbc\xde\xa3\x41\xcb\x29\xd0\x5e\x70\x67\x50\x93\x6d\x98\xa8\xd3\x67\x0f\x68\xb1\xeb\x38\x47\x07\x10\x1b\xd2\xe2\x18\x68\x6d\x40\xbb\xa3\x40\xba\x21\xf2\x8e\x81\xfb\xf6\x92\x77\x2f\x70\xe8\xdb\xb2\x36\xbf\x30\x91\xc5\x21\xe7\x45\xcc\x34\x0c\x48\x8e\xd0\xf2\x9b\x7c\x3c\xbd\x1c\x04\x3e\x07\xe8\x7c\x2f\x84\x7a\x48\x4d\x1f\xba\xe1\x76\x45\x7b\x60\xe0\x01\xca\xee\x04\xca\x31\xbe\x73\x5f\xa3\x70\x0c\xad\x1f\xa5\xf5\x76\xd5\xbb\xd2\x7e\xfb\x30\x90\xcf\xfa\x67\x7a\xe6\xc3\x37\x42\x19\xe2\xc9\x9c\x61\x4c\xe7\xd1\x77\x55\x86\x6e\x8f\x7b\x85\x42\x33\xa3\xaa\x57\xae\xfd\xd5\xcc\x9c\x56\x68\xe2\xde\x0e\xa8\x2c\xa9\xb0\x7d\xf0\x54\x2d\x80\xf2\x48\x39\x3d\x98\x1a\x6d\x0b\x9d\xba\x53\xfb\xce\xf8\xd1\x7e\xbb\x60\x4f\x06\xf5\xce\xda\xab\xeb\xca\xcb\xd5\xac\x20\xda\x72\x3b\xa2\x4b\x38\xd7\xb5\x89\xbe\x42\xd9\xb9\x73\xc4\x0c\x6d\xb7\xd9\xf8\x8d\xbd\x3e\x9c\xf5\x53\x68\x48\x14\x36\x8f\x09\xc5\x92\xf1\x21\xd1\x09\x07\x1c\xbe\xa7\x91\xf3\x6a\xc8\xc1\x57\xb0\xdd\xc5\xc6\x1d\xad\x76\x1d\xa8\x82\x0e\x4c\x38\xfe\xa5\x8c\xc5\x0a\x40\x5d\xa1\xbb\x98\xd1\xfb\x74\x61\xed\x1a\x98\xaf\x3c\x8c\x1e\xe3\xc2\x92\x29\x74\x3e\x99\xd0\xf9\x41\x50\xd0\x38\x4b\x57\x7e\x5b\x7a\x0e\xe6\xce\x4e\xd7\x19\x35\x57\xbb\x3c\x3c\xd2\x5e\x4f\x4b\x4c\xf7\x0f\x4d\x2b\x91\x5d\x94\xa6\x95\xc8\x69\x25\x72\x5a\x89\x7c\xb8\x95\xc8\x07\x80\x8c\xda\x9c\x64\x7b\xb7\x71\xdf\x57\x12\x4b\x9a\x1f\x72\x0c\x13\x03\xad\x3c\xd5\x4e\xde\x8e\x57\x13\x6d\x34\x86\xcf\x97\xe6\xa4\x68\xc4\xb0\xf6\xc9\xc2\xeb\x8d\x0b\xd7\xcd\xfe\xba\xa6\xf5\x30\xeb\x30\x33\xbe\xc7\x56\x27\xab\x08\xd9\x6d\xbb\x09\xee\x7c\x2d\xcf\xee\x87\x38\xac\xc8\xdd\x90\x9a\x58\x4a\x4e\x96\xa9\x79\x79\xf3\xde\x20\xf0\x96\xe3\x24\x19\xeb\xba\xf2\x53\x19\xab\x12\xaf\x47\xb3\xa0\x3e\xef\x9b\x8d\x6d\x6d\x7b\xde\x3b\x3b\x1a\xc0\x3f\x95\x7e\xed\x78\xfb\x76\xb8\xaf\xb3\xdd\xc5\xeb\x95\xed\x5a\x62\x41\x82\xb3\x54\x6e\x80\x4a\x92\x6f\x36\xbd\x34\xae\xde\x6f\xa4\xc0\xbc\x08\xe3\x84\xfc\x1d\xb6\xe3\xd0\x62\x38\x95\x9b\x57\xe7\x71\x12\x91\x80\xc8\x31\x69\x5e\x60\x21\x6e\x19\x0f\xc7\xa4\x79\x96\x28\x3e\x47\x54\x65\x41\x36\x08\x40\x88\x1f\x58\x08\x56\xaa\xd5\xbf\xaf\xad\x96\xd7\xd6\xcf\x87\xf5\x34\x0f\x71\x93\x6e\x26\xed\x98\x5b\x9f\x4f\xcf\x95\x34\xc6\xd7\x11\xfa\xb0\x81\x22\x1a\xdb\xdf\x8e\xdc\xc3\xb9\xf8\xdd\x5d\x3c\x74\xe6\xea\xb7\x8b\xbf\xf5\x6e\xb3\x46\x2e\x64\xf4\xab\x3c\x4e\xcf\x36\x1d\xfe\xfa\xb8\x36\xba\x8a\xd8\xad\xf6\xc6\x41\x2a\x37\x8c\x17\x0f\xda\xfe\xda\xe7\x65\xbc\x71\x2c\x36\x57\x8a\x47\x12\x4c\xf1\xbd\x77\x6b\xa4\x50\x7e\x77\x7b\x22\x60\x89\xef\xcd\xf5\xb9\x0c\x97\x79\x0d\x2b\x35\x43\xcb\x3d\x24\xf1\x78\xfc\xf8\xcb\x1f\x15\x06\xe2\x78\xd8\x51\x21\xd9\x1f\xf0\xf5\x8f\x86\xa4\x50\xfa\xb1\x47\x43\xa5\xdd\x69\x14\xe8\xa3\xc0\x86\x91\xa7\x81\x50\xb4\x7c\xc0\x81\x80\x77\x7a\x9f\xc6\xc2\xa9\x8c\x05\x33\xb0\x3b\x31\xa4\xf4\xd7\x1b\x26\x55\x97\x7c\x65\xf8\x69\x1a\x84\x8e\x41\x78\xd9\xec\xc5\x11\x16\x1e\x74\x91\xf5\x56\xf5\x57\x49\x47\x5c\x92\xa9\x1e\x99\x36\xf4\xdb\xb1\x0e\xd3\x78\x02\xb0\x9b\x25\xcb\xe9\xe9\x1d\x0d\x44\x01\x42\x08\x91\x64\xd9\xdd\x37\x08\x17\xef\xf9\xe5\x0f\xbd\x46\x91\xf5\xf9\x89\x92\x37\xdd\x89\x59\x44\x1f\x9c\xee\x34\x1e\xbe\x47\x83\x32\x72\x8e\x37\xdf\xac\x69\x38\xef\x75\xb0\xda\xdb\xac\x83\x94\x2f\x39\xa6\x62\x05\x1c\x25\x9c\x49\x16\xb0\xa8\x3c\xc7\x7e\x76\x71\x3e\x6f\xb5\x24\xe7\xe8\xb7\xb9\xc7\x6c\x43\x92\xee\x21\xd4\x17\xa1\x7f\xba\x35\xfe\xae\x39\xbc\xde\xba\x69\xd9\x8e\xe1\x62\xde\x64\x7d\x16\x88\x1b\xed\x29\x11\xfd\x4f\xa9\xff\x99\x90\xc4\xf6\xf4\xf9\x6e\xe9\x28\x23\xd7\xca\xe5\xee\xee\x9f\x63\xb1\x5b\xfb\x10\xd7\x2f\x1d\xf2\xe3\xbf\xb9\xb5\x6f\xa4\x6d\x7d\x25\x79\xfb\x24\x31\xea\x56\xbe\x5d\x53\xcd\x2d\x36\xa3\x6d\xdf\xab\x1c\xb8\x6d\x6f\xc0\x98\xa7\xdd\xaa\x86\x8c\x1d\x39\xa3\x9d\x70\x2b\x9b\x68\xd9\xfd\x33\xfe\xa9\xb6\x4a\x2e\x63\x0f\xcf\x68\x27\xd9\x4c\xb9\x46\x6d\xcb\xbe\xa1\xa8\xd6\x5f\xc6\xd6\x9f\xf1\x4f\xf4\xd4\xb4\x78\xd0\xd6\xf4\x13\x3c\x3b\xac\xd0\xdc\x90\x34\xda\xc9\xb4\x9a\x1a\x8d\xbd\x93\x87\xd4\xe2\x21\x1b\xb3\x2b\xd1\xbe\xe7\x69\xd4\x53\x67\xd5\x40\xa0\xe3\x19\x3f\x6d\x1a\xbc\x0e\x86\x3c\x10\xb4\x3d\x2a\xcd\x78\x32\xe6\xab\xbd\x36\xc9\xf4\x3a\x58\xae\xc3\xf4\x47\xea\xbf\xfb\x47\xff\x0d\x00\x00\xff\xff\xd2\x32\x5a\x28\x38\x9d\x00\x00") - -func v2SchemaJsonBytes() ([]byte, error) { - return bindataRead( - _v2SchemaJson, - "v2/schema.json", - ) -} - -func v2SchemaJson() (*asset, error) { - bytes, err := v2SchemaJsonBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "v2/schema.json", size: 40248, mode: os.FileMode(0640), modTime: time.Unix(1568964748, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xab, 0x88, 0x5e, 0xf, 0xbf, 0x17, 0x74, 0x0, 0xb2, 0x5a, 0x7f, 0xbc, 0x58, 0xcd, 0xc, 0x25, 0x73, 0xd5, 0x29, 0x1c, 0x7a, 0xd0, 0xce, 0x79, 0xd4, 0x89, 0x31, 0x27, 0x90, 0xf2, 0xff, 0xe6}} - return a, nil -} - -// Asset loads and returns the asset for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func Asset(name string) ([]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) - } - return a.bytes, nil - } - return nil, fmt.Errorf("Asset %s not found", name) -} - -// AssetString returns the asset contents as a string (instead of a []byte). -func AssetString(name string) (string, error) { - data, err := Asset(name) - return string(data), err -} - -// MustAsset is like Asset but panics when Asset would return an error. -// It simplifies safe initialization of global variables. -func MustAsset(name string) []byte { - a, err := Asset(name) - if err != nil { - panic("asset: Asset(" + name + "): " + err.Error()) - } - - return a -} - -// MustAssetString is like AssetString but panics when Asset would return an -// error. It simplifies safe initialization of global variables. -func MustAssetString(name string) string { - return string(MustAsset(name)) -} - -// AssetInfo loads and returns the asset info for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func AssetInfo(name string) (os.FileInfo, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) - } - return a.info, nil - } - return nil, fmt.Errorf("AssetInfo %s not found", name) -} - -// AssetDigest returns the digest of the file with the given name. It returns an -// error if the asset could not be found or the digest could not be loaded. -func AssetDigest(name string) ([sha256.Size]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) - } - return a.digest, nil - } - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) -} - -// Digests returns a map of all known files and their checksums. -func Digests() (map[string][sha256.Size]byte, error) { - mp := make(map[string][sha256.Size]byte, len(_bindata)) - for name := range _bindata { - a, err := _bindata[name]() - if err != nil { - return nil, err - } - mp[name] = a.digest - } - return mp, nil -} - -// AssetNames returns the names of the assets. -func AssetNames() []string { - names := make([]string, 0, len(_bindata)) - for name := range _bindata { - names = append(names, name) - } - return names -} - -// _bindata is a table, holding each asset generator, mapped to its name. -var _bindata = map[string]func() (*asset, error){ - "jsonschema-draft-04.json": jsonschemaDraft04Json, - - "v2/schema.json": v2SchemaJson, -} - -// AssetDir returns the file names below a certain -// directory embedded in the file by go-bindata. -// For example if you run go-bindata on data/... and data contains the -// following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png -// then AssetDir("data") would return []string{"foo.txt", "img"}, -// AssetDir("data/img") would return []string{"a.png", "b.png"}, -// AssetDir("foo.txt") and AssetDir("notexist") would return an error, and -// AssetDir("") will return []string{"data"}. -func AssetDir(name string) ([]string, error) { - node := _bintree - if len(name) != 0 { - canonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(canonicalName, "/") - for _, p := range pathList { - node = node.Children[p] - if node == nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - } - } - if node.Func != nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - rv := make([]string, 0, len(node.Children)) - for childName := range node.Children { - rv = append(rv, childName) - } - return rv, nil -} - -type bintree struct { - Func func() (*asset, error) - Children map[string]*bintree -} - -var _bintree = &bintree{nil, map[string]*bintree{ - "jsonschema-draft-04.json": {jsonschemaDraft04Json, map[string]*bintree{}}, - "v2": {nil, map[string]*bintree{ - "schema.json": {v2SchemaJson, map[string]*bintree{}}, - }}, -}} - -// RestoreAsset restores an asset under the given directory. -func RestoreAsset(dir, name string) error { - data, err := Asset(name) - if err != nil { - return err - } - info, err := AssetInfo(name) - if err != nil { - return err - } - err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) - if err != nil { - return err - } - err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) - if err != nil { - return err - } - return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) -} - -// RestoreAssets restores an asset under the given directory recursively. -func RestoreAssets(dir, name string) error { - children, err := AssetDir(name) - // File - if err != nil { - return RestoreAsset(dir, name) - } - // Dir - for _, child := range children { - err = RestoreAssets(dir, filepath.Join(name, child)) - if err != nil { - return err - } - } - return nil -} - -func _filePath(dir, name string) string { - canonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) -} diff --git a/vendor/github.com/go-openapi/spec/cache.go b/vendor/github.com/go-openapi/spec/cache.go deleted file mode 100644 index 122993b44..000000000 --- a/vendor/github.com/go-openapi/spec/cache.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "sync" -) - -// ResolutionCache a cache for resolving urls -type ResolutionCache interface { - Get(string) (interface{}, bool) - Set(string, interface{}) -} - -type simpleCache struct { - lock sync.RWMutex - store map[string]interface{} -} - -func (s *simpleCache) ShallowClone() ResolutionCache { - store := make(map[string]interface{}, len(s.store)) - s.lock.RLock() - for k, v := range s.store { - store[k] = v - } - s.lock.RUnlock() - - return &simpleCache{ - store: store, - } -} - -// Get retrieves a cached URI -func (s *simpleCache) Get(uri string) (interface{}, bool) { - s.lock.RLock() - v, ok := s.store[uri] - - s.lock.RUnlock() - return v, ok -} - -// Set caches a URI -func (s *simpleCache) Set(uri string, data interface{}) { - s.lock.Lock() - s.store[uri] = data - s.lock.Unlock() -} - -var ( - // resCache is a package level cache for $ref resolution and expansion. - // It is initialized lazily by methods that have the need for it: no - // memory is allocated unless some expander methods are called. - // - // It is initialized with JSON schema and swagger schema, - // which do not mutate during normal operations. - // - // All subsequent utilizations of this cache are produced from a shallow - // clone of this initial version. - resCache *simpleCache - onceCache sync.Once - - _ ResolutionCache = &simpleCache{} -) - -// initResolutionCache initializes the URI resolution cache. To be wrapped in a sync.Once.Do call. -func initResolutionCache() { - resCache = defaultResolutionCache() -} - -func defaultResolutionCache() *simpleCache { - return &simpleCache{store: map[string]interface{}{ - "http://swagger.io/v2/schema.json": MustLoadSwagger20Schema(), - "http://json-schema.org/draft-04/schema": MustLoadJSONSchemaDraft04(), - }} -} - -func cacheOrDefault(cache ResolutionCache) ResolutionCache { - onceCache.Do(initResolutionCache) - - if cache != nil { - return cache - } - - // get a shallow clone of the base cache with swagger and json schema - return resCache.ShallowClone() -} diff --git a/vendor/github.com/go-openapi/spec/contact_info.go b/vendor/github.com/go-openapi/spec/contact_info.go deleted file mode 100644 index 2f7bb219b..000000000 --- a/vendor/github.com/go-openapi/spec/contact_info.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "encoding/json" - - "github.com/go-openapi/swag" -) - -// ContactInfo contact information for the exposed API. -// -// For more information: http://goo.gl/8us55a#contactObject -type ContactInfo struct { - ContactInfoProps - VendorExtensible -} - -// ContactInfoProps hold the properties of a ContactInfo object -type ContactInfoProps struct { - Name string `json:"name,omitempty"` - URL string `json:"url,omitempty"` - Email string `json:"email,omitempty"` -} - -// UnmarshalJSON hydrates ContactInfo from json -func (c *ContactInfo) UnmarshalJSON(data []byte) error { - if err := json.Unmarshal(data, &c.ContactInfoProps); err != nil { - return err - } - return json.Unmarshal(data, &c.VendorExtensible) -} - -// MarshalJSON produces ContactInfo as json -func (c ContactInfo) MarshalJSON() ([]byte, error) { - b1, err := json.Marshal(c.ContactInfoProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(c.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2), nil -} diff --git a/vendor/github.com/go-openapi/spec/debug.go b/vendor/github.com/go-openapi/spec/debug.go deleted file mode 100644 index fc889f6d0..000000000 --- a/vendor/github.com/go-openapi/spec/debug.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "fmt" - "log" - "os" - "path" - "runtime" -) - -// Debug is true when the SWAGGER_DEBUG env var is not empty. -// -// It enables a more verbose logging of this package. -var Debug = os.Getenv("SWAGGER_DEBUG") != "" - -var ( - // specLogger is a debug logger for this package - specLogger *log.Logger -) - -func init() { - debugOptions() -} - -func debugOptions() { - specLogger = log.New(os.Stdout, "spec:", log.LstdFlags) -} - -func debugLog(msg string, args ...interface{}) { - // A private, trivial trace logger, based on go-openapi/spec/expander.go:debugLog() - if Debug { - _, file1, pos1, _ := runtime.Caller(1) - specLogger.Printf("%s:%d: %s", path.Base(file1), pos1, fmt.Sprintf(msg, args...)) - } -} diff --git a/vendor/github.com/go-openapi/spec/errors.go b/vendor/github.com/go-openapi/spec/errors.go deleted file mode 100644 index 6992c7ba7..000000000 --- a/vendor/github.com/go-openapi/spec/errors.go +++ /dev/null @@ -1,19 +0,0 @@ -package spec - -import "errors" - -// Error codes -var ( - // ErrUnknownTypeForReference indicates that a resolved reference was found in an unsupported container type - ErrUnknownTypeForReference = errors.New("unknown type for the resolved reference") - - // ErrResolveRefNeedsAPointer indicates that a $ref target must be a valid JSON pointer - ErrResolveRefNeedsAPointer = errors.New("resolve ref: target needs to be a pointer") - - // ErrDerefUnsupportedType indicates that a resolved reference was found in an unsupported container type. - // At the moment, $ref are supported only inside: schemas, parameters, responses, path items - ErrDerefUnsupportedType = errors.New("deref: unsupported type") - - // ErrExpandUnsupportedType indicates that $ref expansion is attempted on some invalid type - ErrExpandUnsupportedType = errors.New("expand: unsupported type. Input should be of type *Parameter or *Response") -) diff --git a/vendor/github.com/go-openapi/spec/expander.go b/vendor/github.com/go-openapi/spec/expander.go deleted file mode 100644 index d4ea889d4..000000000 --- a/vendor/github.com/go-openapi/spec/expander.go +++ /dev/null @@ -1,594 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "encoding/json" - "fmt" -) - -// ExpandOptions provides options for the spec expander. -// -// RelativeBase is the path to the root document. This can be a remote URL or a path to a local file. -// -// If left empty, the root document is assumed to be located in the current working directory: -// all relative $ref's will be resolved from there. -// -// PathLoader injects a document loading method. By default, this resolves to the function provided by the SpecLoader package variable. -// -type ExpandOptions struct { - RelativeBase string // the path to the root document to expand. This is a file, not a directory - SkipSchemas bool // do not expand schemas, just paths, parameters and responses - ContinueOnError bool // continue expanding even after and error is found - PathLoader func(string) (json.RawMessage, error) `json:"-"` // the document loading method that takes a path as input and yields a json document - AbsoluteCircularRef bool // circular $ref remaining after expansion remain absolute URLs -} - -func optionsOrDefault(opts *ExpandOptions) *ExpandOptions { - if opts != nil { - clone := *opts // shallow clone to avoid internal changes to be propagated to the caller - if clone.RelativeBase != "" { - clone.RelativeBase = normalizeBase(clone.RelativeBase) - } - // if the relative base is empty, let the schema loader choose a pseudo root document - return &clone - } - return &ExpandOptions{} -} - -// ExpandSpec expands the references in a swagger spec -func ExpandSpec(spec *Swagger, options *ExpandOptions) error { - options = optionsOrDefault(options) - resolver := defaultSchemaLoader(spec, options, nil, nil) - - specBasePath := options.RelativeBase - - if !options.SkipSchemas { - for key, definition := range spec.Definitions { - parentRefs := make([]string, 0, 10) - parentRefs = append(parentRefs, fmt.Sprintf("#/definitions/%s", key)) - - def, err := expandSchema(definition, parentRefs, resolver, specBasePath) - if resolver.shouldStopOnError(err) { - return err - } - if def != nil { - spec.Definitions[key] = *def - } - } - } - - for key := range spec.Parameters { - parameter := spec.Parameters[key] - if err := expandParameterOrResponse(¶meter, resolver, specBasePath); resolver.shouldStopOnError(err) { - return err - } - spec.Parameters[key] = parameter - } - - for key := range spec.Responses { - response := spec.Responses[key] - if err := expandParameterOrResponse(&response, resolver, specBasePath); resolver.shouldStopOnError(err) { - return err - } - spec.Responses[key] = response - } - - if spec.Paths != nil { - for key := range spec.Paths.Paths { - pth := spec.Paths.Paths[key] - if err := expandPathItem(&pth, resolver, specBasePath); resolver.shouldStopOnError(err) { - return err - } - spec.Paths.Paths[key] = pth - } - } - - return nil -} - -const rootBase = ".root" - -// baseForRoot loads in the cache the root document and produces a fake ".root" base path entry -// for further $ref resolution -// -// Setting the cache is optional and this parameter may safely be left to nil. -func baseForRoot(root interface{}, cache ResolutionCache) string { - if root == nil { - return "" - } - - // cache the root document to resolve $ref's - normalizedBase := normalizeBase(rootBase) - cache.Set(normalizedBase, root) - - return normalizedBase -} - -// ExpandSchema expands the refs in the schema object with reference to the root object. -// -// go-openapi/validate uses this function. -// -// Notice that it is impossible to reference a json schema in a different document other than root -// (use ExpandSchemaWithBasePath to resolve external references). -// -// Setting the cache is optional and this parameter may safely be left to nil. -func ExpandSchema(schema *Schema, root interface{}, cache ResolutionCache) error { - cache = cacheOrDefault(cache) - if root == nil { - root = schema - } - - opts := &ExpandOptions{ - // when a root is specified, cache the root as an in-memory document for $ref retrieval - RelativeBase: baseForRoot(root, cache), - SkipSchemas: false, - ContinueOnError: false, - } - - return ExpandSchemaWithBasePath(schema, cache, opts) -} - -// ExpandSchemaWithBasePath expands the refs in the schema object, base path configured through expand options. -// -// Setting the cache is optional and this parameter may safely be left to nil. -func ExpandSchemaWithBasePath(schema *Schema, cache ResolutionCache, opts *ExpandOptions) error { - if schema == nil { - return nil - } - - cache = cacheOrDefault(cache) - - opts = optionsOrDefault(opts) - - resolver := defaultSchemaLoader(nil, opts, cache, nil) - - parentRefs := make([]string, 0, 10) - s, err := expandSchema(*schema, parentRefs, resolver, opts.RelativeBase) - if err != nil { - return err - } - if s != nil { - // guard for when continuing on error - *schema = *s - } - - return nil -} - -func expandItems(target Schema, parentRefs []string, resolver *schemaLoader, basePath string) (*Schema, error) { - if target.Items == nil { - return &target, nil - } - - // array - if target.Items.Schema != nil { - t, err := expandSchema(*target.Items.Schema, parentRefs, resolver, basePath) - if err != nil { - return nil, err - } - *target.Items.Schema = *t - } - - // tuple - for i := range target.Items.Schemas { - t, err := expandSchema(target.Items.Schemas[i], parentRefs, resolver, basePath) - if err != nil { - return nil, err - } - target.Items.Schemas[i] = *t - } - - return &target, nil -} - -func expandSchema(target Schema, parentRefs []string, resolver *schemaLoader, basePath string) (*Schema, error) { - if target.Ref.String() == "" && target.Ref.IsRoot() { - newRef := normalizeRef(&target.Ref, basePath) - target.Ref = *newRef - return &target, nil - } - - // change the base path of resolution when an ID is encountered - // otherwise the basePath should inherit the parent's - if target.ID != "" { - basePath, _ = resolver.setSchemaID(target, target.ID, basePath) - } - - if target.Ref.String() != "" { - return expandSchemaRef(target, parentRefs, resolver, basePath) - } - - for k := range target.Definitions { - tt, err := expandSchema(target.Definitions[k], parentRefs, resolver, basePath) - if resolver.shouldStopOnError(err) { - return &target, err - } - if tt != nil { - target.Definitions[k] = *tt - } - } - - t, err := expandItems(target, parentRefs, resolver, basePath) - if resolver.shouldStopOnError(err) { - return &target, err - } - if t != nil { - target = *t - } - - for i := range target.AllOf { - t, err := expandSchema(target.AllOf[i], parentRefs, resolver, basePath) - if resolver.shouldStopOnError(err) { - return &target, err - } - if t != nil { - target.AllOf[i] = *t - } - } - - for i := range target.AnyOf { - t, err := expandSchema(target.AnyOf[i], parentRefs, resolver, basePath) - if resolver.shouldStopOnError(err) { - return &target, err - } - if t != nil { - target.AnyOf[i] = *t - } - } - - for i := range target.OneOf { - t, err := expandSchema(target.OneOf[i], parentRefs, resolver, basePath) - if resolver.shouldStopOnError(err) { - return &target, err - } - if t != nil { - target.OneOf[i] = *t - } - } - - if target.Not != nil { - t, err := expandSchema(*target.Not, parentRefs, resolver, basePath) - if resolver.shouldStopOnError(err) { - return &target, err - } - if t != nil { - *target.Not = *t - } - } - - for k := range target.Properties { - t, err := expandSchema(target.Properties[k], parentRefs, resolver, basePath) - if resolver.shouldStopOnError(err) { - return &target, err - } - if t != nil { - target.Properties[k] = *t - } - } - - if target.AdditionalProperties != nil && target.AdditionalProperties.Schema != nil { - t, err := expandSchema(*target.AdditionalProperties.Schema, parentRefs, resolver, basePath) - if resolver.shouldStopOnError(err) { - return &target, err - } - if t != nil { - *target.AdditionalProperties.Schema = *t - } - } - - for k := range target.PatternProperties { - t, err := expandSchema(target.PatternProperties[k], parentRefs, resolver, basePath) - if resolver.shouldStopOnError(err) { - return &target, err - } - if t != nil { - target.PatternProperties[k] = *t - } - } - - for k := range target.Dependencies { - if target.Dependencies[k].Schema != nil { - t, err := expandSchema(*target.Dependencies[k].Schema, parentRefs, resolver, basePath) - if resolver.shouldStopOnError(err) { - return &target, err - } - if t != nil { - *target.Dependencies[k].Schema = *t - } - } - } - - if target.AdditionalItems != nil && target.AdditionalItems.Schema != nil { - t, err := expandSchema(*target.AdditionalItems.Schema, parentRefs, resolver, basePath) - if resolver.shouldStopOnError(err) { - return &target, err - } - if t != nil { - *target.AdditionalItems.Schema = *t - } - } - return &target, nil -} - -func expandSchemaRef(target Schema, parentRefs []string, resolver *schemaLoader, basePath string) (*Schema, error) { - // if a Ref is found, all sibling fields are skipped - // Ref also changes the resolution scope of children expandSchema - - // here the resolution scope is changed because a $ref was encountered - normalizedRef := normalizeRef(&target.Ref, basePath) - normalizedBasePath := normalizedRef.RemoteURI() - - if resolver.isCircular(normalizedRef, basePath, parentRefs...) { - // this means there is a cycle in the recursion tree: return the Ref - // - circular refs cannot be expanded. We leave them as ref. - // - denormalization means that a new local file ref is set relative to the original basePath - debugLog("short circuit circular ref: basePath: %s, normalizedPath: %s, normalized ref: %s", - basePath, normalizedBasePath, normalizedRef.String()) - if !resolver.options.AbsoluteCircularRef { - target.Ref = denormalizeRef(normalizedRef, resolver.context.basePath, resolver.context.rootID) - } else { - target.Ref = *normalizedRef - } - return &target, nil - } - - var t *Schema - err := resolver.Resolve(&target.Ref, &t, basePath) - if resolver.shouldStopOnError(err) { - return nil, err - } - - if t == nil { - // guard for when continuing on error - return &target, nil - } - - parentRefs = append(parentRefs, normalizedRef.String()) - transitiveResolver := resolver.transitiveResolver(basePath, target.Ref) - - basePath = resolver.updateBasePath(transitiveResolver, normalizedBasePath) - - return expandSchema(*t, parentRefs, transitiveResolver, basePath) -} - -func expandPathItem(pathItem *PathItem, resolver *schemaLoader, basePath string) error { - if pathItem == nil { - return nil - } - - parentRefs := make([]string, 0, 10) - if err := resolver.deref(pathItem, parentRefs, basePath); resolver.shouldStopOnError(err) { - return err - } - - if pathItem.Ref.String() != "" { - transitiveResolver := resolver.transitiveResolver(basePath, pathItem.Ref) - basePath = transitiveResolver.updateBasePath(resolver, basePath) - resolver = transitiveResolver - } - - pathItem.Ref = Ref{} - for i := range pathItem.Parameters { - if err := expandParameterOrResponse(&(pathItem.Parameters[i]), resolver, basePath); resolver.shouldStopOnError(err) { - return err - } - } - - ops := []*Operation{ - pathItem.Get, - pathItem.Head, - pathItem.Options, - pathItem.Put, - pathItem.Post, - pathItem.Patch, - pathItem.Delete, - } - for _, op := range ops { - if err := expandOperation(op, resolver, basePath); resolver.shouldStopOnError(err) { - return err - } - } - - return nil -} - -func expandOperation(op *Operation, resolver *schemaLoader, basePath string) error { - if op == nil { - return nil - } - - for i := range op.Parameters { - param := op.Parameters[i] - if err := expandParameterOrResponse(¶m, resolver, basePath); resolver.shouldStopOnError(err) { - return err - } - op.Parameters[i] = param - } - - if op.Responses == nil { - return nil - } - - responses := op.Responses - if err := expandParameterOrResponse(responses.Default, resolver, basePath); resolver.shouldStopOnError(err) { - return err - } - - for code := range responses.StatusCodeResponses { - response := responses.StatusCodeResponses[code] - if err := expandParameterOrResponse(&response, resolver, basePath); resolver.shouldStopOnError(err) { - return err - } - responses.StatusCodeResponses[code] = response - } - - return nil -} - -// ExpandResponseWithRoot expands a response based on a root document, not a fetchable document -// -// Notice that it is impossible to reference a json schema in a different document other than root -// (use ExpandResponse to resolve external references). -// -// Setting the cache is optional and this parameter may safely be left to nil. -func ExpandResponseWithRoot(response *Response, root interface{}, cache ResolutionCache) error { - cache = cacheOrDefault(cache) - opts := &ExpandOptions{ - RelativeBase: baseForRoot(root, cache), - } - resolver := defaultSchemaLoader(root, opts, cache, nil) - - return expandParameterOrResponse(response, resolver, opts.RelativeBase) -} - -// ExpandResponse expands a response based on a basepath -// -// All refs inside response will be resolved relative to basePath -func ExpandResponse(response *Response, basePath string) error { - opts := optionsOrDefault(&ExpandOptions{ - RelativeBase: basePath, - }) - resolver := defaultSchemaLoader(nil, opts, nil, nil) - - return expandParameterOrResponse(response, resolver, opts.RelativeBase) -} - -// ExpandParameterWithRoot expands a parameter based on a root document, not a fetchable document. -// -// Notice that it is impossible to reference a json schema in a different document other than root -// (use ExpandParameter to resolve external references). -func ExpandParameterWithRoot(parameter *Parameter, root interface{}, cache ResolutionCache) error { - cache = cacheOrDefault(cache) - - opts := &ExpandOptions{ - RelativeBase: baseForRoot(root, cache), - } - resolver := defaultSchemaLoader(root, opts, cache, nil) - - return expandParameterOrResponse(parameter, resolver, opts.RelativeBase) -} - -// ExpandParameter expands a parameter based on a basepath. -// This is the exported version of expandParameter -// all refs inside parameter will be resolved relative to basePath -func ExpandParameter(parameter *Parameter, basePath string) error { - opts := optionsOrDefault(&ExpandOptions{ - RelativeBase: basePath, - }) - resolver := defaultSchemaLoader(nil, opts, nil, nil) - - return expandParameterOrResponse(parameter, resolver, opts.RelativeBase) -} - -func getRefAndSchema(input interface{}) (*Ref, *Schema, error) { - var ( - ref *Ref - sch *Schema - ) - - switch refable := input.(type) { - case *Parameter: - if refable == nil { - return nil, nil, nil - } - ref = &refable.Ref - sch = refable.Schema - case *Response: - if refable == nil { - return nil, nil, nil - } - ref = &refable.Ref - sch = refable.Schema - default: - return nil, nil, fmt.Errorf("unsupported type: %T: %w", input, ErrExpandUnsupportedType) - } - - return ref, sch, nil -} - -func expandParameterOrResponse(input interface{}, resolver *schemaLoader, basePath string) error { - ref, _, err := getRefAndSchema(input) - if err != nil { - return err - } - - if ref == nil { - return nil - } - - parentRefs := make([]string, 0, 10) - if err = resolver.deref(input, parentRefs, basePath); resolver.shouldStopOnError(err) { - return err - } - - ref, sch, _ := getRefAndSchema(input) - if ref.String() != "" { - transitiveResolver := resolver.transitiveResolver(basePath, *ref) - basePath = resolver.updateBasePath(transitiveResolver, basePath) - resolver = transitiveResolver - } - - if sch == nil { - // nothing to be expanded - if ref != nil { - *ref = Ref{} - } - return nil - } - - if sch.Ref.String() != "" { - rebasedRef, ern := NewRef(normalizeURI(sch.Ref.String(), basePath)) - if ern != nil { - return ern - } - - switch { - case resolver.isCircular(&rebasedRef, basePath, parentRefs...): - // this is a circular $ref: stop expansion - if !resolver.options.AbsoluteCircularRef { - sch.Ref = denormalizeRef(&rebasedRef, resolver.context.basePath, resolver.context.rootID) - } else { - sch.Ref = rebasedRef - } - case !resolver.options.SkipSchemas: - // schema expanded to a $ref in another root - sch.Ref = rebasedRef - debugLog("rebased to: %s", sch.Ref.String()) - default: - // skip schema expansion but rebase $ref to schema - sch.Ref = denormalizeRef(&rebasedRef, resolver.context.basePath, resolver.context.rootID) - } - } - - if ref != nil { - *ref = Ref{} - } - - // expand schema - if !resolver.options.SkipSchemas { - s, err := expandSchema(*sch, parentRefs, resolver, basePath) - if resolver.shouldStopOnError(err) { - return err - } - if s == nil { - // guard for when continuing on error - return nil - } - *sch = *s - } - - return nil -} diff --git a/vendor/github.com/go-openapi/spec/external_docs.go b/vendor/github.com/go-openapi/spec/external_docs.go deleted file mode 100644 index 88add91b2..000000000 --- a/vendor/github.com/go-openapi/spec/external_docs.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -// ExternalDocumentation allows referencing an external resource for -// extended documentation. -// -// For more information: http://goo.gl/8us55a#externalDocumentationObject -type ExternalDocumentation struct { - Description string `json:"description,omitempty"` - URL string `json:"url,omitempty"` -} diff --git a/vendor/github.com/go-openapi/spec/go.mod b/vendor/github.com/go-openapi/spec/go.mod deleted file mode 100644 index 39aab5f7e..000000000 --- a/vendor/github.com/go-openapi/spec/go.mod +++ /dev/null @@ -1,12 +0,0 @@ -module github.com/go-openapi/spec - -require ( - github.com/go-openapi/jsonpointer v0.19.5 - github.com/go-openapi/jsonreference v0.19.6 - github.com/go-openapi/swag v0.19.15 - github.com/stretchr/testify v1.6.1 - golang.org/x/text v0.3.7 // indirect - gopkg.in/yaml.v2 v2.4.0 -) - -go 1.13 diff --git a/vendor/github.com/go-openapi/spec/go.sum b/vendor/github.com/go-openapi/spec/go.sum deleted file mode 100644 index 3a2f52263..000000000 --- a/vendor/github.com/go-openapi/spec/go.sum +++ /dev/null @@ -1,59 +0,0 @@ -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs= -github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= -github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -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/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -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/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758 h1:aEpZnXcAmXkd6AvLb2OPt+EN1Zu/8Ne3pCqPjja5PXY= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -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-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/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 h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/vendor/github.com/go-openapi/spec/header.go b/vendor/github.com/go-openapi/spec/header.go deleted file mode 100644 index 9dfd17b18..000000000 --- a/vendor/github.com/go-openapi/spec/header.go +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "encoding/json" - "strings" - - "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" -) - -const ( - jsonArray = "array" -) - -// HeaderProps describes a response header -type HeaderProps struct { - Description string `json:"description,omitempty"` -} - -// Header describes a header for a response of the API -// -// For more information: http://goo.gl/8us55a#headerObject -type Header struct { - CommonValidations - SimpleSchema - VendorExtensible - HeaderProps -} - -// ResponseHeader creates a new header instance for use in a response -func ResponseHeader() *Header { - return new(Header) -} - -// WithDescription sets the description on this response, allows for chaining -func (h *Header) WithDescription(description string) *Header { - h.Description = description - return h -} - -// Typed a fluent builder method for the type of parameter -func (h *Header) Typed(tpe, format string) *Header { - h.Type = tpe - h.Format = format - return h -} - -// CollectionOf a fluent builder method for an array item -func (h *Header) CollectionOf(items *Items, format string) *Header { - h.Type = jsonArray - h.Items = items - h.CollectionFormat = format - return h -} - -// WithDefault sets the default value on this item -func (h *Header) WithDefault(defaultValue interface{}) *Header { - h.Default = defaultValue - return h -} - -// WithMaxLength sets a max length value -func (h *Header) WithMaxLength(max int64) *Header { - h.MaxLength = &max - return h -} - -// WithMinLength sets a min length value -func (h *Header) WithMinLength(min int64) *Header { - h.MinLength = &min - return h -} - -// WithPattern sets a pattern value -func (h *Header) WithPattern(pattern string) *Header { - h.Pattern = pattern - return h -} - -// WithMultipleOf sets a multiple of value -func (h *Header) WithMultipleOf(number float64) *Header { - h.MultipleOf = &number - return h -} - -// WithMaximum sets a maximum number value -func (h *Header) WithMaximum(max float64, exclusive bool) *Header { - h.Maximum = &max - h.ExclusiveMaximum = exclusive - return h -} - -// WithMinimum sets a minimum number value -func (h *Header) WithMinimum(min float64, exclusive bool) *Header { - h.Minimum = &min - h.ExclusiveMinimum = exclusive - return h -} - -// WithEnum sets a the enum values (replace) -func (h *Header) WithEnum(values ...interface{}) *Header { - h.Enum = append([]interface{}{}, values...) - return h -} - -// WithMaxItems sets the max items -func (h *Header) WithMaxItems(size int64) *Header { - h.MaxItems = &size - return h -} - -// WithMinItems sets the min items -func (h *Header) WithMinItems(size int64) *Header { - h.MinItems = &size - return h -} - -// UniqueValues dictates that this array can only have unique items -func (h *Header) UniqueValues() *Header { - h.UniqueItems = true - return h -} - -// AllowDuplicates this array can have duplicates -func (h *Header) AllowDuplicates() *Header { - h.UniqueItems = false - return h -} - -// WithValidations is a fluent method to set header validations -func (h *Header) WithValidations(val CommonValidations) *Header { - h.SetValidations(SchemaValidations{CommonValidations: val}) - return h -} - -// MarshalJSON marshal this to JSON -func (h Header) MarshalJSON() ([]byte, error) { - b1, err := json.Marshal(h.CommonValidations) - if err != nil { - return nil, err - } - b2, err := json.Marshal(h.SimpleSchema) - if err != nil { - return nil, err - } - b3, err := json.Marshal(h.HeaderProps) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2, b3), nil -} - -// UnmarshalJSON unmarshals this header from JSON -func (h *Header) UnmarshalJSON(data []byte) error { - if err := json.Unmarshal(data, &h.CommonValidations); err != nil { - return err - } - if err := json.Unmarshal(data, &h.SimpleSchema); err != nil { - return err - } - if err := json.Unmarshal(data, &h.VendorExtensible); err != nil { - return err - } - return json.Unmarshal(data, &h.HeaderProps) -} - -// JSONLookup look up a value by the json property name -func (h Header) JSONLookup(token string) (interface{}, error) { - if ex, ok := h.Extensions[token]; ok { - return &ex, nil - } - - r, _, err := jsonpointer.GetForToken(h.CommonValidations, token) - if err != nil && !strings.HasPrefix(err.Error(), "object has no field") { - return nil, err - } - if r != nil { - return r, nil - } - r, _, err = jsonpointer.GetForToken(h.SimpleSchema, token) - if err != nil && !strings.HasPrefix(err.Error(), "object has no field") { - return nil, err - } - if r != nil { - return r, nil - } - r, _, err = jsonpointer.GetForToken(h.HeaderProps, token) - return r, err -} diff --git a/vendor/github.com/go-openapi/spec/info.go b/vendor/github.com/go-openapi/spec/info.go deleted file mode 100644 index c458b49b2..000000000 --- a/vendor/github.com/go-openapi/spec/info.go +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "encoding/json" - "strings" - - "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" -) - -// Extensions vendor specific extensions -type Extensions map[string]interface{} - -// Add adds a value to these extensions -func (e Extensions) Add(key string, value interface{}) { - realKey := strings.ToLower(key) - e[realKey] = value -} - -// GetString gets a string value from the extensions -func (e Extensions) GetString(key string) (string, bool) { - if v, ok := e[strings.ToLower(key)]; ok { - str, ok := v.(string) - return str, ok - } - return "", false -} - -// GetBool gets a string value from the extensions -func (e Extensions) GetBool(key string) (bool, bool) { - if v, ok := e[strings.ToLower(key)]; ok { - str, ok := v.(bool) - return str, ok - } - return false, false -} - -// GetStringSlice gets a string value from the extensions -func (e Extensions) GetStringSlice(key string) ([]string, bool) { - if v, ok := e[strings.ToLower(key)]; ok { - arr, isSlice := v.([]interface{}) - if !isSlice { - return nil, false - } - var strs []string - for _, iface := range arr { - str, isString := iface.(string) - if !isString { - return nil, false - } - strs = append(strs, str) - } - return strs, ok - } - return nil, false -} - -// VendorExtensible composition block. -type VendorExtensible struct { - Extensions Extensions -} - -// AddExtension adds an extension to this extensible object -func (v *VendorExtensible) AddExtension(key string, value interface{}) { - if value == nil { - return - } - if v.Extensions == nil { - v.Extensions = make(map[string]interface{}) - } - v.Extensions.Add(key, value) -} - -// MarshalJSON marshals the extensions to json -func (v VendorExtensible) MarshalJSON() ([]byte, error) { - toser := make(map[string]interface{}) - for k, v := range v.Extensions { - lk := strings.ToLower(k) - if strings.HasPrefix(lk, "x-") { - toser[k] = v - } - } - return json.Marshal(toser) -} - -// UnmarshalJSON for this extensible object -func (v *VendorExtensible) UnmarshalJSON(data []byte) error { - var d map[string]interface{} - if err := json.Unmarshal(data, &d); err != nil { - return err - } - for k, vv := range d { - lk := strings.ToLower(k) - if strings.HasPrefix(lk, "x-") { - if v.Extensions == nil { - v.Extensions = map[string]interface{}{} - } - v.Extensions[k] = vv - } - } - return nil -} - -// InfoProps the properties for an info definition -type InfoProps struct { - Description string `json:"description,omitempty"` - Title string `json:"title,omitempty"` - TermsOfService string `json:"termsOfService,omitempty"` - Contact *ContactInfo `json:"contact,omitempty"` - License *License `json:"license,omitempty"` - Version string `json:"version,omitempty"` -} - -// Info object provides metadata about the API. -// The metadata can be used by the clients if needed, and can be presented in the Swagger-UI for convenience. -// -// For more information: http://goo.gl/8us55a#infoObject -type Info struct { - VendorExtensible - InfoProps -} - -// JSONLookup look up a value by the json property name -func (i Info) JSONLookup(token string) (interface{}, error) { - if ex, ok := i.Extensions[token]; ok { - return &ex, nil - } - r, _, err := jsonpointer.GetForToken(i.InfoProps, token) - return r, err -} - -// MarshalJSON marshal this to JSON -func (i Info) MarshalJSON() ([]byte, error) { - b1, err := json.Marshal(i.InfoProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(i.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2), nil -} - -// UnmarshalJSON marshal this from JSON -func (i *Info) UnmarshalJSON(data []byte) error { - if err := json.Unmarshal(data, &i.InfoProps); err != nil { - return err - } - return json.Unmarshal(data, &i.VendorExtensible) -} diff --git a/vendor/github.com/go-openapi/spec/items.go b/vendor/github.com/go-openapi/spec/items.go deleted file mode 100644 index e2afb2133..000000000 --- a/vendor/github.com/go-openapi/spec/items.go +++ /dev/null @@ -1,234 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "encoding/json" - "strings" - - "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" -) - -const ( - jsonRef = "$ref" -) - -// SimpleSchema describe swagger simple schemas for parameters and headers -type SimpleSchema struct { - Type string `json:"type,omitempty"` - Nullable bool `json:"nullable,omitempty"` - Format string `json:"format,omitempty"` - Items *Items `json:"items,omitempty"` - CollectionFormat string `json:"collectionFormat,omitempty"` - Default interface{} `json:"default,omitempty"` - Example interface{} `json:"example,omitempty"` -} - -// TypeName return the type (or format) of a simple schema -func (s *SimpleSchema) TypeName() string { - if s.Format != "" { - return s.Format - } - return s.Type -} - -// ItemsTypeName yields the type of items in a simple schema array -func (s *SimpleSchema) ItemsTypeName() string { - if s.Items == nil { - return "" - } - return s.Items.TypeName() -} - -// Items a limited subset of JSON-Schema's items object. -// It is used by parameter definitions that are not located in "body". -// -// For more information: http://goo.gl/8us55a#items-object -type Items struct { - Refable - CommonValidations - SimpleSchema - VendorExtensible -} - -// NewItems creates a new instance of items -func NewItems() *Items { - return &Items{} -} - -// Typed a fluent builder method for the type of item -func (i *Items) Typed(tpe, format string) *Items { - i.Type = tpe - i.Format = format - return i -} - -// AsNullable flags this schema as nullable. -func (i *Items) AsNullable() *Items { - i.Nullable = true - return i -} - -// CollectionOf a fluent builder method for an array item -func (i *Items) CollectionOf(items *Items, format string) *Items { - i.Type = jsonArray - i.Items = items - i.CollectionFormat = format - return i -} - -// WithDefault sets the default value on this item -func (i *Items) WithDefault(defaultValue interface{}) *Items { - i.Default = defaultValue - return i -} - -// WithMaxLength sets a max length value -func (i *Items) WithMaxLength(max int64) *Items { - i.MaxLength = &max - return i -} - -// WithMinLength sets a min length value -func (i *Items) WithMinLength(min int64) *Items { - i.MinLength = &min - return i -} - -// WithPattern sets a pattern value -func (i *Items) WithPattern(pattern string) *Items { - i.Pattern = pattern - return i -} - -// WithMultipleOf sets a multiple of value -func (i *Items) WithMultipleOf(number float64) *Items { - i.MultipleOf = &number - return i -} - -// WithMaximum sets a maximum number value -func (i *Items) WithMaximum(max float64, exclusive bool) *Items { - i.Maximum = &max - i.ExclusiveMaximum = exclusive - return i -} - -// WithMinimum sets a minimum number value -func (i *Items) WithMinimum(min float64, exclusive bool) *Items { - i.Minimum = &min - i.ExclusiveMinimum = exclusive - return i -} - -// WithEnum sets a the enum values (replace) -func (i *Items) WithEnum(values ...interface{}) *Items { - i.Enum = append([]interface{}{}, values...) - return i -} - -// WithMaxItems sets the max items -func (i *Items) WithMaxItems(size int64) *Items { - i.MaxItems = &size - return i -} - -// WithMinItems sets the min items -func (i *Items) WithMinItems(size int64) *Items { - i.MinItems = &size - return i -} - -// UniqueValues dictates that this array can only have unique items -func (i *Items) UniqueValues() *Items { - i.UniqueItems = true - return i -} - -// AllowDuplicates this array can have duplicates -func (i *Items) AllowDuplicates() *Items { - i.UniqueItems = false - return i -} - -// WithValidations is a fluent method to set Items validations -func (i *Items) WithValidations(val CommonValidations) *Items { - i.SetValidations(SchemaValidations{CommonValidations: val}) - return i -} - -// UnmarshalJSON hydrates this items instance with the data from JSON -func (i *Items) UnmarshalJSON(data []byte) error { - var validations CommonValidations - if err := json.Unmarshal(data, &validations); err != nil { - return err - } - var ref Refable - if err := json.Unmarshal(data, &ref); err != nil { - return err - } - var simpleSchema SimpleSchema - if err := json.Unmarshal(data, &simpleSchema); err != nil { - return err - } - var vendorExtensible VendorExtensible - if err := json.Unmarshal(data, &vendorExtensible); err != nil { - return err - } - i.Refable = ref - i.CommonValidations = validations - i.SimpleSchema = simpleSchema - i.VendorExtensible = vendorExtensible - return nil -} - -// MarshalJSON converts this items object to JSON -func (i Items) MarshalJSON() ([]byte, error) { - b1, err := json.Marshal(i.CommonValidations) - if err != nil { - return nil, err - } - b2, err := json.Marshal(i.SimpleSchema) - if err != nil { - return nil, err - } - b3, err := json.Marshal(i.Refable) - if err != nil { - return nil, err - } - b4, err := json.Marshal(i.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b4, b3, b1, b2), nil -} - -// JSONLookup look up a value by the json property name -func (i Items) JSONLookup(token string) (interface{}, error) { - if token == jsonRef { - return &i.Ref, nil - } - - r, _, err := jsonpointer.GetForToken(i.CommonValidations, token) - if err != nil && !strings.HasPrefix(err.Error(), "object has no field") { - return nil, err - } - if r != nil { - return r, nil - } - r, _, err = jsonpointer.GetForToken(i.SimpleSchema, token) - return r, err -} diff --git a/vendor/github.com/go-openapi/spec/license.go b/vendor/github.com/go-openapi/spec/license.go deleted file mode 100644 index b42f80368..000000000 --- a/vendor/github.com/go-openapi/spec/license.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "encoding/json" - - "github.com/go-openapi/swag" -) - -// License information for the exposed API. -// -// For more information: http://goo.gl/8us55a#licenseObject -type License struct { - LicenseProps - VendorExtensible -} - -// LicenseProps holds the properties of a License object -type LicenseProps struct { - Name string `json:"name,omitempty"` - URL string `json:"url,omitempty"` -} - -// UnmarshalJSON hydrates License from json -func (l *License) UnmarshalJSON(data []byte) error { - if err := json.Unmarshal(data, &l.LicenseProps); err != nil { - return err - } - return json.Unmarshal(data, &l.VendorExtensible) -} - -// MarshalJSON produces License as json -func (l License) MarshalJSON() ([]byte, error) { - b1, err := json.Marshal(l.LicenseProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(l.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2), nil -} diff --git a/vendor/github.com/go-openapi/spec/normalizer.go b/vendor/github.com/go-openapi/spec/normalizer.go deleted file mode 100644 index d6c483971..000000000 --- a/vendor/github.com/go-openapi/spec/normalizer.go +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "net/url" - "path" - "strings" -) - -const fileScheme = "file" - -// normalizeURI ensures that all $ref paths used internally by the expander are canonicalized. -// -// NOTE(windows): there is a tolerance over the strict URI format on windows. -// -// The normalizer accepts relative file URLs like 'Path\File.JSON' as well as absolute file URLs like -// 'C:\Path\file.Yaml'. -// -// Both are canonicalized with a "file://" scheme, slashes and a lower-cased path: -// 'file:///c:/path/file.yaml' -// -// URLs can be specified with a file scheme, like in 'file:///folder/file.json' or -// 'file:///c:\folder\File.json'. -// -// URLs like file://C:\folder are considered invalid (i.e. there is no host 'c:\folder') and a "repair" -// is attempted. -// -// The base path argument is assumed to be canonicalized (e.g. using normalizeBase()). -func normalizeURI(refPath, base string) string { - refURL, err := url.Parse(refPath) - if err != nil { - specLogger.Printf("warning: invalid URI in $ref %q: %v", refPath, err) - refURL, refPath = repairURI(refPath) - } - - fixWindowsURI(refURL, refPath) // noop on non-windows OS - - refURL.Path = path.Clean(refURL.Path) - if refURL.Path == "." { - refURL.Path = "" - } - - r := MustCreateRef(refURL.String()) - if r.IsCanonical() { - return refURL.String() - } - - baseURL, _ := url.Parse(base) - if path.IsAbs(refURL.Path) { - baseURL.Path = refURL.Path - } else if refURL.Path != "" { - baseURL.Path = path.Join(path.Dir(baseURL.Path), refURL.Path) - } - // copying fragment from ref to base - baseURL.Fragment = refURL.Fragment - - return baseURL.String() -} - -// denormalizeRef returns the simplest notation for a normalized $ref, given the path of the original root document. -// -// When calling this, we assume that: -// * $ref is a canonical URI -// * originalRelativeBase is a canonical URI -// -// denormalizeRef is currently used when we rewrite a $ref after a circular $ref has been detected. -// In this case, expansion stops and normally renders the internal canonical $ref. -// -// This internal $ref is eventually rebased to the original RelativeBase used for the expansion. -// -// There is a special case for schemas that are anchored with an "id": -// in that case, the rebasing is performed // against the id only if this is an anchor for the initial root document. -// All other intermediate "id"'s found along the way are ignored for the purpose of rebasing. -// -func denormalizeRef(ref *Ref, originalRelativeBase, id string) Ref { - debugLog("denormalizeRef called:\n$ref: %q\noriginal: %s\nroot ID:%s", ref.String(), originalRelativeBase, id) - - if ref.String() == "" || ref.IsRoot() || ref.HasFragmentOnly { - // short circuit: $ref to current doc - return *ref - } - - if id != "" { - idBaseURL, err := url.Parse(id) - if err == nil { // if the schema id is not usable as a URI, ignore it - if ref, ok := rebase(ref, idBaseURL, true); ok { // rebase, but keep references to root unchaged (do not want $ref: "") - // $ref relative to the ID of the schema in the root document - return ref - } - } - } - - originalRelativeBaseURL, _ := url.Parse(originalRelativeBase) - - r, _ := rebase(ref, originalRelativeBaseURL, false) - - return r -} - -func rebase(ref *Ref, v *url.URL, notEqual bool) (Ref, bool) { - var newBase url.URL - - u := ref.GetURL() - - if u.Scheme != v.Scheme || u.Host != v.Host { - return *ref, false - } - - docPath := v.Path - v.Path = path.Dir(v.Path) - - if v.Path == "." { - v.Path = "" - } else if !strings.HasSuffix(v.Path, "/") { - v.Path += "/" - } - - newBase.Fragment = u.Fragment - - if strings.HasPrefix(u.Path, docPath) { - newBase.Path = strings.TrimPrefix(u.Path, docPath) - } else { - newBase.Path = strings.TrimPrefix(u.Path, v.Path) - } - - if notEqual && newBase.Path == "" && newBase.Fragment == "" { - // do not want rebasing to end up in an empty $ref - return *ref, false - } - - if path.IsAbs(newBase.Path) { - // whenever we end up with an absolute path, specify the scheme and host - newBase.Scheme = v.Scheme - newBase.Host = v.Host - } - - return MustCreateRef(newBase.String()), true -} - -// normalizeRef canonicalize a Ref, using a canonical relativeBase as its absolute anchor -func normalizeRef(ref *Ref, relativeBase string) *Ref { - r := MustCreateRef(normalizeURI(ref.String(), relativeBase)) - return &r -} - -// normalizeBase performs a normalization of the input base path. -// -// This always yields a canonical URI (absolute), usable for the document cache. -// -// It ensures that all further internal work on basePath may safely assume -// a non-empty, cross-platform, canonical URI (i.e. absolute). -// -// This normalization tolerates windows paths (e.g. C:\x\y\File.dat) and transform this -// in a file:// URL with lower cased drive letter and path. -// -// See also: https://en.wikipedia.org/wiki/File_URI_scheme -func normalizeBase(in string) string { - u, err := url.Parse(in) - if err != nil { - specLogger.Printf("warning: invalid URI in RelativeBase %q: %v", in, err) - u, in = repairURI(in) - } - - u.Fragment = "" // any fragment in the base is irrelevant - - fixWindowsURI(u, in) // noop on non-windows OS - - u.Path = path.Clean(u.Path) - if u.Path == "." { // empty after Clean() - u.Path = "" - } - - if u.Scheme != "" { - if path.IsAbs(u.Path) || u.Scheme != fileScheme { - // this is absolute or explicitly not a local file: we're good - return u.String() - } - } - - // no scheme or file scheme with relative path: assume file and make it absolute - // enforce scheme file://... with absolute path. - // - // If the input path is relative, we anchor the path to the current working directory. - // NOTE: we may end up with a host component. Leave it unchanged: e.g. file://host/folder/file.json - - u.Scheme = fileScheme - u.Path = absPath(u.Path) // platform-dependent - u.RawQuery = "" // any query component is irrelevant for a base - return u.String() -} diff --git a/vendor/github.com/go-openapi/spec/normalizer_nonwindows.go b/vendor/github.com/go-openapi/spec/normalizer_nonwindows.go deleted file mode 100644 index c8a064534..000000000 --- a/vendor/github.com/go-openapi/spec/normalizer_nonwindows.go +++ /dev/null @@ -1,43 +0,0 @@ -// +build !windows - -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "net/url" - "path/filepath" -) - -// absPath makes a file path absolute and compatible with a URI path component. -// -// The parameter must be a path, not an URI. -func absPath(in string) string { - anchored, err := filepath.Abs(in) - if err != nil { - specLogger.Printf("warning: could not resolve current working directory: %v", err) - return in - } - return anchored -} - -func repairURI(in string) (*url.URL, string) { - u, _ := url.Parse("") - debugLog("repaired URI: original: %q, repaired: %q", in, "") - return u, "" -} - -func fixWindowsURI(u *url.URL, in string) { -} diff --git a/vendor/github.com/go-openapi/spec/normalizer_windows.go b/vendor/github.com/go-openapi/spec/normalizer_windows.go deleted file mode 100644 index fe2d1ecd4..000000000 --- a/vendor/github.com/go-openapi/spec/normalizer_windows.go +++ /dev/null @@ -1,154 +0,0 @@ -// -build windows - -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "net/url" - "os" - "path" - "path/filepath" - "strings" -) - -// absPath makes a file path absolute and compatible with a URI path component -// -// The parameter must be a path, not an URI. -func absPath(in string) string { - // NOTE(windows): filepath.Abs exhibits a special behavior on windows for empty paths. - // See https://github.com/golang/go/issues/24441 - if in == "" { - in = "." - } - - anchored, err := filepath.Abs(in) - if err != nil { - specLogger.Printf("warning: could not resolve current working directory: %v", err) - return in - } - - pth := strings.ReplaceAll(strings.ToLower(anchored), `\`, `/`) - if !strings.HasPrefix(pth, "/") { - pth = "/" + pth - } - - return path.Clean(pth) -} - -// repairURI tolerates invalid file URIs with common typos -// such as 'file://E:\folder\file', that break the regular URL parser. -// -// Adopting the same defaults as for unixes (e.g. return an empty path) would -// result into a counter-intuitive result for that case (e.g. E:\folder\file is -// eventually resolved as the current directory). The repair will detect the missing "/". -// -// Note that this only works for the file scheme. -func repairURI(in string) (*url.URL, string) { - const prefix = fileScheme + "://" - if !strings.HasPrefix(in, prefix) { - // giving up: resolve to empty path - u, _ := url.Parse("") - - return u, "" - } - - // attempt the repair, stripping the scheme should be sufficient - u, _ := url.Parse(strings.TrimPrefix(in, prefix)) - debugLog("repaired URI: original: %q, repaired: %q", in, u.String()) - - return u, u.String() -} - -// fixWindowsURI tolerates an absolute file path on windows such as C:\Base\File.yaml or \\host\share\Base\File.yaml -// and makes it a canonical URI: file:///c:/base/file.yaml -// -// Catch 22 notes for Windows: -// -// * There may be a drive letter on windows (it is lower-cased) -// * There may be a share UNC, e.g. \\server\folder\data.xml -// * Paths are case insensitive -// * Paths may already contain slashes -// * Paths must be slashed -// -// NOTE: there is no escaping. "/" may be valid separators just like "\". -// We don't use ToSlash() (which escapes everything) because windows now also -// tolerates the use of "/". Hence, both C:\File.yaml and C:/File.yaml will work. -func fixWindowsURI(u *url.URL, in string) { - drive := filepath.VolumeName(in) - - if len(drive) > 0 { - if len(u.Scheme) == 1 && strings.EqualFold(u.Scheme, drive[:1]) { // a path with a drive letter - u.Scheme = fileScheme - u.Host = "" - u.Path = strings.Join([]string{drive, u.Opaque, u.Path}, `/`) // reconstruct the full path component (no fragment, no query) - } else if u.Host == "" && strings.HasPrefix(u.Path, drive) { // a path with a \\host volume - // NOTE: the special host@port syntax for UNC is not supported (yet) - u.Scheme = fileScheme - - // this is a modified version of filepath.Dir() to apply on the VolumeName itself - i := len(drive) - 1 - for i >= 0 && !os.IsPathSeparator(drive[i]) { - i-- - } - host := drive[:i] // \\host\share => host - - u.Path = strings.TrimPrefix(u.Path, host) - u.Host = strings.TrimPrefix(host, `\\`) - } - - u.Opaque = "" - u.Path = strings.ReplaceAll(strings.ToLower(u.Path), `\`, `/`) - - // ensure we form an absolute path - if !strings.HasPrefix(u.Path, "/") { - u.Path = "/" + u.Path - } - - u.Path = path.Clean(u.Path) - - return - } - - if u.Scheme == fileScheme { - // Handle dodgy cases for file://{...} URIs on windows. - // A canonical URI should always be followed by an absolute path. - // - // Examples: - // * file:///folder/file => valid, unchanged - // * file:///c:\folder\file => slashed - // * file:///./folder/file => valid, cleaned to remove the dot - // * file:///.\folder\file => remapped to cwd - // * file:///. => dodgy, remapped to / (consistent with the behavior on unix) - // * file:///.. => dodgy, remapped to / (consistent with the behavior on unix) - if (!path.IsAbs(u.Path) && !filepath.IsAbs(u.Path)) || (strings.HasPrefix(u.Path, `/.`) && strings.Contains(u.Path, `\`)) { - // ensure we form an absolute path - u.Path, _ = filepath.Abs(strings.TrimLeft(u.Path, `/`)) - if !strings.HasPrefix(u.Path, "/") { - u.Path = "/" + u.Path - } - } - u.Path = strings.ToLower(u.Path) - } - - // NOTE: lower case normalization does not propagate to inner resources, - // generated when rebasing: when joining a relative URI with a file to an absolute base, - // only the base is currently lower-cased. - // - // For now, we assume this is good enough for most use cases - // and try not to generate too many differences - // between the output produced on different platforms. - u.Path = path.Clean(strings.ReplaceAll(u.Path, `\`, `/`)) -} diff --git a/vendor/github.com/go-openapi/spec/operation.go b/vendor/github.com/go-openapi/spec/operation.go deleted file mode 100644 index 995ce6acb..000000000 --- a/vendor/github.com/go-openapi/spec/operation.go +++ /dev/null @@ -1,397 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "bytes" - "encoding/gob" - "encoding/json" - "sort" - - "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" -) - -func init() { - gob.Register(map[string]interface{}{}) - gob.Register([]interface{}{}) -} - -// OperationProps describes an operation -// -// NOTES: -// - schemes, when present must be from [http, https, ws, wss]: see validate -// - Security is handled as a special case: see MarshalJSON function -type OperationProps struct { - Description string `json:"description,omitempty"` - Consumes []string `json:"consumes,omitempty"` - Produces []string `json:"produces,omitempty"` - Schemes []string `json:"schemes,omitempty"` - Tags []string `json:"tags,omitempty"` - Summary string `json:"summary,omitempty"` - ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"` - ID string `json:"operationId,omitempty"` - Deprecated bool `json:"deprecated,omitempty"` - Security []map[string][]string `json:"security,omitempty"` - Parameters []Parameter `json:"parameters,omitempty"` - Responses *Responses `json:"responses,omitempty"` -} - -// MarshalJSON takes care of serializing operation properties to JSON -// -// We use a custom marhaller here to handle a special cases related to -// the Security field. We need to preserve zero length slice -// while omitting the field when the value is nil/unset. -func (op OperationProps) MarshalJSON() ([]byte, error) { - type Alias OperationProps - if op.Security == nil { - return json.Marshal(&struct { - Security []map[string][]string `json:"security,omitempty"` - *Alias - }{ - Security: op.Security, - Alias: (*Alias)(&op), - }) - } - return json.Marshal(&struct { - Security []map[string][]string `json:"security"` - *Alias - }{ - Security: op.Security, - Alias: (*Alias)(&op), - }) -} - -// Operation describes a single API operation on a path. -// -// For more information: http://goo.gl/8us55a#operationObject -type Operation struct { - VendorExtensible - OperationProps -} - -// SuccessResponse gets a success response model -func (o *Operation) SuccessResponse() (*Response, int, bool) { - if o.Responses == nil { - return nil, 0, false - } - - responseCodes := make([]int, 0, len(o.Responses.StatusCodeResponses)) - for k := range o.Responses.StatusCodeResponses { - if k >= 200 && k < 300 { - responseCodes = append(responseCodes, k) - } - } - if len(responseCodes) > 0 { - sort.Ints(responseCodes) - v := o.Responses.StatusCodeResponses[responseCodes[0]] - return &v, responseCodes[0], true - } - - return o.Responses.Default, 0, false -} - -// JSONLookup look up a value by the json property name -func (o Operation) JSONLookup(token string) (interface{}, error) { - if ex, ok := o.Extensions[token]; ok { - return &ex, nil - } - r, _, err := jsonpointer.GetForToken(o.OperationProps, token) - return r, err -} - -// UnmarshalJSON hydrates this items instance with the data from JSON -func (o *Operation) UnmarshalJSON(data []byte) error { - if err := json.Unmarshal(data, &o.OperationProps); err != nil { - return err - } - return json.Unmarshal(data, &o.VendorExtensible) -} - -// MarshalJSON converts this items object to JSON -func (o Operation) MarshalJSON() ([]byte, error) { - b1, err := json.Marshal(o.OperationProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(o.VendorExtensible) - if err != nil { - return nil, err - } - concated := swag.ConcatJSON(b1, b2) - return concated, nil -} - -// NewOperation creates a new operation instance. -// It expects an ID as parameter but not passing an ID is also valid. -func NewOperation(id string) *Operation { - op := new(Operation) - op.ID = id - return op -} - -// WithID sets the ID property on this operation, allows for chaining. -func (o *Operation) WithID(id string) *Operation { - o.ID = id - return o -} - -// WithDescription sets the description on this operation, allows for chaining -func (o *Operation) WithDescription(description string) *Operation { - o.Description = description - return o -} - -// WithSummary sets the summary on this operation, allows for chaining -func (o *Operation) WithSummary(summary string) *Operation { - o.Summary = summary - return o -} - -// WithExternalDocs sets/removes the external docs for/from this operation. -// When you pass empty strings as params the external documents will be removed. -// When you pass non-empty string as one value then those values will be used on the external docs object. -// So when you pass a non-empty description, you should also pass the url and vice versa. -func (o *Operation) WithExternalDocs(description, url string) *Operation { - if description == "" && url == "" { - o.ExternalDocs = nil - return o - } - - if o.ExternalDocs == nil { - o.ExternalDocs = &ExternalDocumentation{} - } - o.ExternalDocs.Description = description - o.ExternalDocs.URL = url - return o -} - -// Deprecate marks the operation as deprecated -func (o *Operation) Deprecate() *Operation { - o.Deprecated = true - return o -} - -// Undeprecate marks the operation as not deprected -func (o *Operation) Undeprecate() *Operation { - o.Deprecated = false - return o -} - -// WithConsumes adds media types for incoming body values -func (o *Operation) WithConsumes(mediaTypes ...string) *Operation { - o.Consumes = append(o.Consumes, mediaTypes...) - return o -} - -// WithProduces adds media types for outgoing body values -func (o *Operation) WithProduces(mediaTypes ...string) *Operation { - o.Produces = append(o.Produces, mediaTypes...) - return o -} - -// WithTags adds tags for this operation -func (o *Operation) WithTags(tags ...string) *Operation { - o.Tags = append(o.Tags, tags...) - return o -} - -// AddParam adds a parameter to this operation, when a parameter for that location -// and with that name already exists it will be replaced -func (o *Operation) AddParam(param *Parameter) *Operation { - if param == nil { - return o - } - - for i, p := range o.Parameters { - if p.Name == param.Name && p.In == param.In { - params := append(o.Parameters[:i], *param) - params = append(params, o.Parameters[i+1:]...) - o.Parameters = params - return o - } - } - - o.Parameters = append(o.Parameters, *param) - return o -} - -// RemoveParam removes a parameter from the operation -func (o *Operation) RemoveParam(name, in string) *Operation { - for i, p := range o.Parameters { - if p.Name == name && p.In == in { - o.Parameters = append(o.Parameters[:i], o.Parameters[i+1:]...) - return o - } - } - return o -} - -// SecuredWith adds a security scope to this operation. -func (o *Operation) SecuredWith(name string, scopes ...string) *Operation { - o.Security = append(o.Security, map[string][]string{name: scopes}) - return o -} - -// WithDefaultResponse adds a default response to the operation. -// Passing a nil value will remove the response -func (o *Operation) WithDefaultResponse(response *Response) *Operation { - return o.RespondsWith(0, response) -} - -// RespondsWith adds a status code response to the operation. -// When the code is 0 the value of the response will be used as default response value. -// When the value of the response is nil it will be removed from the operation -func (o *Operation) RespondsWith(code int, response *Response) *Operation { - if o.Responses == nil { - o.Responses = new(Responses) - } - if code == 0 { - o.Responses.Default = response - return o - } - if response == nil { - delete(o.Responses.StatusCodeResponses, code) - return o - } - if o.Responses.StatusCodeResponses == nil { - o.Responses.StatusCodeResponses = make(map[int]Response) - } - o.Responses.StatusCodeResponses[code] = *response - return o -} - -type opsAlias OperationProps - -type gobAlias struct { - Security []map[string]struct { - List []string - Pad bool - } - Alias *opsAlias - SecurityIsEmpty bool -} - -// GobEncode provides a safe gob encoder for Operation, including empty security requirements -func (o Operation) GobEncode() ([]byte, error) { - raw := struct { - Ext VendorExtensible - Props OperationProps - }{ - Ext: o.VendorExtensible, - Props: o.OperationProps, - } - var b bytes.Buffer - err := gob.NewEncoder(&b).Encode(raw) - return b.Bytes(), err -} - -// GobDecode provides a safe gob decoder for Operation, including empty security requirements -func (o *Operation) GobDecode(b []byte) error { - var raw struct { - Ext VendorExtensible - Props OperationProps - } - - buf := bytes.NewBuffer(b) - err := gob.NewDecoder(buf).Decode(&raw) - if err != nil { - return err - } - o.VendorExtensible = raw.Ext - o.OperationProps = raw.Props - return nil -} - -// GobEncode provides a safe gob encoder for Operation, including empty security requirements -func (op OperationProps) GobEncode() ([]byte, error) { - raw := gobAlias{ - Alias: (*opsAlias)(&op), - } - - var b bytes.Buffer - if op.Security == nil { - // nil security requirement - err := gob.NewEncoder(&b).Encode(raw) - return b.Bytes(), err - } - - if len(op.Security) == 0 { - // empty, but non-nil security requirement - raw.SecurityIsEmpty = true - raw.Alias.Security = nil - err := gob.NewEncoder(&b).Encode(raw) - return b.Bytes(), err - } - - raw.Security = make([]map[string]struct { - List []string - Pad bool - }, 0, len(op.Security)) - for _, req := range op.Security { - v := make(map[string]struct { - List []string - Pad bool - }, len(req)) - for k, val := range req { - v[k] = struct { - List []string - Pad bool - }{ - List: val, - } - } - raw.Security = append(raw.Security, v) - } - - err := gob.NewEncoder(&b).Encode(raw) - return b.Bytes(), err -} - -// GobDecode provides a safe gob decoder for Operation, including empty security requirements -func (op *OperationProps) GobDecode(b []byte) error { - var raw gobAlias - - buf := bytes.NewBuffer(b) - err := gob.NewDecoder(buf).Decode(&raw) - if err != nil { - return err - } - if raw.Alias == nil { - return nil - } - - switch { - case raw.SecurityIsEmpty: - // empty, but non-nil security requirement - raw.Alias.Security = []map[string][]string{} - case len(raw.Alias.Security) == 0: - // nil security requirement - raw.Alias.Security = nil - default: - raw.Alias.Security = make([]map[string][]string, 0, len(raw.Security)) - for _, req := range raw.Security { - v := make(map[string][]string, len(req)) - for k, val := range req { - v[k] = make([]string, 0, len(val.List)) - v[k] = append(v[k], val.List...) - } - raw.Alias.Security = append(raw.Alias.Security, v) - } - } - - *op = *(*OperationProps)(raw.Alias) - return nil -} diff --git a/vendor/github.com/go-openapi/spec/parameter.go b/vendor/github.com/go-openapi/spec/parameter.go deleted file mode 100644 index 2b2b89b67..000000000 --- a/vendor/github.com/go-openapi/spec/parameter.go +++ /dev/null @@ -1,326 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "encoding/json" - "strings" - - "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" -) - -// QueryParam creates a query parameter -func QueryParam(name string) *Parameter { - return &Parameter{ParamProps: ParamProps{Name: name, In: "query"}} -} - -// HeaderParam creates a header parameter, this is always required by default -func HeaderParam(name string) *Parameter { - return &Parameter{ParamProps: ParamProps{Name: name, In: "header", Required: true}} -} - -// PathParam creates a path parameter, this is always required -func PathParam(name string) *Parameter { - return &Parameter{ParamProps: ParamProps{Name: name, In: "path", Required: true}} -} - -// BodyParam creates a body parameter -func BodyParam(name string, schema *Schema) *Parameter { - return &Parameter{ParamProps: ParamProps{Name: name, In: "body", Schema: schema}} -} - -// FormDataParam creates a body parameter -func FormDataParam(name string) *Parameter { - return &Parameter{ParamProps: ParamProps{Name: name, In: "formData"}} -} - -// FileParam creates a body parameter -func FileParam(name string) *Parameter { - return &Parameter{ParamProps: ParamProps{Name: name, In: "formData"}, - SimpleSchema: SimpleSchema{Type: "file"}} -} - -// SimpleArrayParam creates a param for a simple array (string, int, date etc) -func SimpleArrayParam(name, tpe, fmt string) *Parameter { - return &Parameter{ParamProps: ParamProps{Name: name}, - SimpleSchema: SimpleSchema{Type: jsonArray, CollectionFormat: "csv", - Items: &Items{SimpleSchema: SimpleSchema{Type: tpe, Format: fmt}}}} -} - -// ParamRef creates a parameter that's a json reference -func ParamRef(uri string) *Parameter { - p := new(Parameter) - p.Ref = MustCreateRef(uri) - return p -} - -// ParamProps describes the specific attributes of an operation parameter -// -// NOTE: -// - Schema is defined when "in" == "body": see validate -// - AllowEmptyValue is allowed where "in" == "query" || "formData" -type ParamProps struct { - Description string `json:"description,omitempty"` - Name string `json:"name,omitempty"` - In string `json:"in,omitempty"` - Required bool `json:"required,omitempty"` - Schema *Schema `json:"schema,omitempty"` - AllowEmptyValue bool `json:"allowEmptyValue,omitempty"` -} - -// Parameter a unique parameter is defined by a combination of a [name](#parameterName) and [location](#parameterIn). -// -// There are five possible parameter types. -// * Path - Used together with [Path Templating](#pathTemplating), where the parameter value is actually part -// of the operation's URL. This does not include the host or base path of the API. For example, in `/items/{itemId}`, -// the path parameter is `itemId`. -// * Query - Parameters that are appended to the URL. For example, in `/items?id=###`, the query parameter is `id`. -// * Header - Custom headers that are expected as part of the request. -// * Body - The payload that's appended to the HTTP request. Since there can only be one payload, there can only be -// _one_ body parameter. The name of the body parameter has no effect on the parameter itself and is used for -// documentation purposes only. Since Form parameters are also in the payload, body and form parameters cannot exist -// together for the same operation. -// * Form - Used to describe the payload of an HTTP request when either `application/x-www-form-urlencoded` or -// `multipart/form-data` are used as the content type of the request (in Swagger's definition, -// the [`consumes`](#operationConsumes) property of an operation). This is the only parameter type that can be used -// to send files, thus supporting the `file` type. Since form parameters are sent in the payload, they cannot be -// declared together with a body parameter for the same operation. Form parameters have a different format based on -// the content-type used (for further details, consult http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4). -// * `application/x-www-form-urlencoded` - Similar to the format of Query parameters but as a payload. -// For example, `foo=1&bar=swagger` - both `foo` and `bar` are form parameters. This is normally used for simple -// parameters that are being transferred. -// * `multipart/form-data` - each parameter takes a section in the payload with an internal header. -// For example, for the header `Content-Disposition: form-data; name="submit-name"` the name of the parameter is -// `submit-name`. This type of form parameters is more commonly used for file transfers. -// -// For more information: http://goo.gl/8us55a#parameterObject -type Parameter struct { - Refable - CommonValidations - SimpleSchema - VendorExtensible - ParamProps -} - -// JSONLookup look up a value by the json property name -func (p Parameter) JSONLookup(token string) (interface{}, error) { - if ex, ok := p.Extensions[token]; ok { - return &ex, nil - } - if token == jsonRef { - return &p.Ref, nil - } - - r, _, err := jsonpointer.GetForToken(p.CommonValidations, token) - if err != nil && !strings.HasPrefix(err.Error(), "object has no field") { - return nil, err - } - if r != nil { - return r, nil - } - r, _, err = jsonpointer.GetForToken(p.SimpleSchema, token) - if err != nil && !strings.HasPrefix(err.Error(), "object has no field") { - return nil, err - } - if r != nil { - return r, nil - } - r, _, err = jsonpointer.GetForToken(p.ParamProps, token) - return r, err -} - -// WithDescription a fluent builder method for the description of the parameter -func (p *Parameter) WithDescription(description string) *Parameter { - p.Description = description - return p -} - -// Named a fluent builder method to override the name of the parameter -func (p *Parameter) Named(name string) *Parameter { - p.Name = name - return p -} - -// WithLocation a fluent builder method to override the location of the parameter -func (p *Parameter) WithLocation(in string) *Parameter { - p.In = in - return p -} - -// Typed a fluent builder method for the type of the parameter value -func (p *Parameter) Typed(tpe, format string) *Parameter { - p.Type = tpe - p.Format = format - return p -} - -// CollectionOf a fluent builder method for an array parameter -func (p *Parameter) CollectionOf(items *Items, format string) *Parameter { - p.Type = jsonArray - p.Items = items - p.CollectionFormat = format - return p -} - -// WithDefault sets the default value on this parameter -func (p *Parameter) WithDefault(defaultValue interface{}) *Parameter { - p.AsOptional() // with default implies optional - p.Default = defaultValue - return p -} - -// AllowsEmptyValues flags this parameter as being ok with empty values -func (p *Parameter) AllowsEmptyValues() *Parameter { - p.AllowEmptyValue = true - return p -} - -// NoEmptyValues flags this parameter as not liking empty values -func (p *Parameter) NoEmptyValues() *Parameter { - p.AllowEmptyValue = false - return p -} - -// AsOptional flags this parameter as optional -func (p *Parameter) AsOptional() *Parameter { - p.Required = false - return p -} - -// AsRequired flags this parameter as required -func (p *Parameter) AsRequired() *Parameter { - if p.Default != nil { // with a default required makes no sense - return p - } - p.Required = true - return p -} - -// WithMaxLength sets a max length value -func (p *Parameter) WithMaxLength(max int64) *Parameter { - p.MaxLength = &max - return p -} - -// WithMinLength sets a min length value -func (p *Parameter) WithMinLength(min int64) *Parameter { - p.MinLength = &min - return p -} - -// WithPattern sets a pattern value -func (p *Parameter) WithPattern(pattern string) *Parameter { - p.Pattern = pattern - return p -} - -// WithMultipleOf sets a multiple of value -func (p *Parameter) WithMultipleOf(number float64) *Parameter { - p.MultipleOf = &number - return p -} - -// WithMaximum sets a maximum number value -func (p *Parameter) WithMaximum(max float64, exclusive bool) *Parameter { - p.Maximum = &max - p.ExclusiveMaximum = exclusive - return p -} - -// WithMinimum sets a minimum number value -func (p *Parameter) WithMinimum(min float64, exclusive bool) *Parameter { - p.Minimum = &min - p.ExclusiveMinimum = exclusive - return p -} - -// WithEnum sets a the enum values (replace) -func (p *Parameter) WithEnum(values ...interface{}) *Parameter { - p.Enum = append([]interface{}{}, values...) - return p -} - -// WithMaxItems sets the max items -func (p *Parameter) WithMaxItems(size int64) *Parameter { - p.MaxItems = &size - return p -} - -// WithMinItems sets the min items -func (p *Parameter) WithMinItems(size int64) *Parameter { - p.MinItems = &size - return p -} - -// UniqueValues dictates that this array can only have unique items -func (p *Parameter) UniqueValues() *Parameter { - p.UniqueItems = true - return p -} - -// AllowDuplicates this array can have duplicates -func (p *Parameter) AllowDuplicates() *Parameter { - p.UniqueItems = false - return p -} - -// WithValidations is a fluent method to set parameter validations -func (p *Parameter) WithValidations(val CommonValidations) *Parameter { - p.SetValidations(SchemaValidations{CommonValidations: val}) - return p -} - -// UnmarshalJSON hydrates this items instance with the data from JSON -func (p *Parameter) UnmarshalJSON(data []byte) error { - if err := json.Unmarshal(data, &p.CommonValidations); err != nil { - return err - } - if err := json.Unmarshal(data, &p.Refable); err != nil { - return err - } - if err := json.Unmarshal(data, &p.SimpleSchema); err != nil { - return err - } - if err := json.Unmarshal(data, &p.VendorExtensible); err != nil { - return err - } - return json.Unmarshal(data, &p.ParamProps) -} - -// MarshalJSON converts this items object to JSON -func (p Parameter) MarshalJSON() ([]byte, error) { - b1, err := json.Marshal(p.CommonValidations) - if err != nil { - return nil, err - } - b2, err := json.Marshal(p.SimpleSchema) - if err != nil { - return nil, err - } - b3, err := json.Marshal(p.Refable) - if err != nil { - return nil, err - } - b4, err := json.Marshal(p.VendorExtensible) - if err != nil { - return nil, err - } - b5, err := json.Marshal(p.ParamProps) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b3, b1, b2, b4, b5), nil -} diff --git a/vendor/github.com/go-openapi/spec/path_item.go b/vendor/github.com/go-openapi/spec/path_item.go deleted file mode 100644 index 68fc8e901..000000000 --- a/vendor/github.com/go-openapi/spec/path_item.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "encoding/json" - - "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" -) - -// PathItemProps the path item specific properties -type PathItemProps struct { - Get *Operation `json:"get,omitempty"` - Put *Operation `json:"put,omitempty"` - Post *Operation `json:"post,omitempty"` - Delete *Operation `json:"delete,omitempty"` - Options *Operation `json:"options,omitempty"` - Head *Operation `json:"head,omitempty"` - Patch *Operation `json:"patch,omitempty"` - Parameters []Parameter `json:"parameters,omitempty"` -} - -// PathItem describes the operations available on a single path. -// A Path Item may be empty, due to [ACL constraints](http://goo.gl/8us55a#securityFiltering). -// The path itself is still exposed to the documentation viewer but they will -// not know which operations and parameters are available. -// -// For more information: http://goo.gl/8us55a#pathItemObject -type PathItem struct { - Refable - VendorExtensible - PathItemProps -} - -// JSONLookup look up a value by the json property name -func (p PathItem) JSONLookup(token string) (interface{}, error) { - if ex, ok := p.Extensions[token]; ok { - return &ex, nil - } - if token == jsonRef { - return &p.Ref, nil - } - r, _, err := jsonpointer.GetForToken(p.PathItemProps, token) - return r, err -} - -// UnmarshalJSON hydrates this items instance with the data from JSON -func (p *PathItem) UnmarshalJSON(data []byte) error { - if err := json.Unmarshal(data, &p.Refable); err != nil { - return err - } - if err := json.Unmarshal(data, &p.VendorExtensible); err != nil { - return err - } - return json.Unmarshal(data, &p.PathItemProps) -} - -// MarshalJSON converts this items object to JSON -func (p PathItem) MarshalJSON() ([]byte, error) { - b3, err := json.Marshal(p.Refable) - if err != nil { - return nil, err - } - b4, err := json.Marshal(p.VendorExtensible) - if err != nil { - return nil, err - } - b5, err := json.Marshal(p.PathItemProps) - if err != nil { - return nil, err - } - concated := swag.ConcatJSON(b3, b4, b5) - return concated, nil -} diff --git a/vendor/github.com/go-openapi/spec/paths.go b/vendor/github.com/go-openapi/spec/paths.go deleted file mode 100644 index 9dc82a290..000000000 --- a/vendor/github.com/go-openapi/spec/paths.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "encoding/json" - "fmt" - "strings" - - "github.com/go-openapi/swag" -) - -// Paths holds the relative paths to the individual endpoints. -// The path is appended to the [`basePath`](http://goo.gl/8us55a#swaggerBasePath) in order -// to construct the full URL. -// The Paths may be empty, due to [ACL constraints](http://goo.gl/8us55a#securityFiltering). -// -// For more information: http://goo.gl/8us55a#pathsObject -type Paths struct { - VendorExtensible - Paths map[string]PathItem `json:"-"` // custom serializer to flatten this, each entry must start with "/" -} - -// JSONLookup look up a value by the json property name -func (p Paths) JSONLookup(token string) (interface{}, error) { - if pi, ok := p.Paths[token]; ok { - return &pi, nil - } - if ex, ok := p.Extensions[token]; ok { - return &ex, nil - } - return nil, fmt.Errorf("object has no field %q", token) -} - -// UnmarshalJSON hydrates this items instance with the data from JSON -func (p *Paths) UnmarshalJSON(data []byte) error { - var res map[string]json.RawMessage - if err := json.Unmarshal(data, &res); err != nil { - return err - } - for k, v := range res { - if strings.HasPrefix(strings.ToLower(k), "x-") { - if p.Extensions == nil { - p.Extensions = make(map[string]interface{}) - } - var d interface{} - if err := json.Unmarshal(v, &d); err != nil { - return err - } - p.Extensions[k] = d - } - if strings.HasPrefix(k, "/") { - if p.Paths == nil { - p.Paths = make(map[string]PathItem) - } - var pi PathItem - if err := json.Unmarshal(v, &pi); err != nil { - return err - } - p.Paths[k] = pi - } - } - return nil -} - -// MarshalJSON converts this items object to JSON -func (p Paths) MarshalJSON() ([]byte, error) { - b1, err := json.Marshal(p.VendorExtensible) - if err != nil { - return nil, err - } - - pths := make(map[string]PathItem) - for k, v := range p.Paths { - if strings.HasPrefix(k, "/") { - pths[k] = v - } - } - b2, err := json.Marshal(pths) - if err != nil { - return nil, err - } - concated := swag.ConcatJSON(b1, b2) - return concated, nil -} diff --git a/vendor/github.com/go-openapi/spec/properties.go b/vendor/github.com/go-openapi/spec/properties.go deleted file mode 100644 index 2af13787a..000000000 --- a/vendor/github.com/go-openapi/spec/properties.go +++ /dev/null @@ -1,91 +0,0 @@ -package spec - -import ( - "bytes" - "encoding/json" - "reflect" - "sort" -) - -// OrderSchemaItem holds a named schema (e.g. from a property of an object) -type OrderSchemaItem struct { - Name string - Schema -} - -// OrderSchemaItems is a sortable slice of named schemas. -// The ordering is defined by the x-order schema extension. -type OrderSchemaItems []OrderSchemaItem - -// MarshalJSON produces a json object with keys defined by the name schemas -// of the OrderSchemaItems slice, keeping the original order of the slice. -func (items OrderSchemaItems) MarshalJSON() ([]byte, error) { - buf := bytes.NewBuffer(nil) - buf.WriteString("{") - for i := range items { - if i > 0 { - buf.WriteString(",") - } - buf.WriteString("\"") - buf.WriteString(items[i].Name) - buf.WriteString("\":") - bs, err := json.Marshal(&items[i].Schema) - if err != nil { - return nil, err - } - buf.Write(bs) - } - buf.WriteString("}") - return buf.Bytes(), nil -} - -func (items OrderSchemaItems) Len() int { return len(items) } -func (items OrderSchemaItems) Swap(i, j int) { items[i], items[j] = items[j], items[i] } -func (items OrderSchemaItems) Less(i, j int) (ret bool) { - ii, oki := items[i].Extensions.GetString("x-order") - ij, okj := items[j].Extensions.GetString("x-order") - if oki { - if okj { - defer func() { - if err := recover(); err != nil { - defer func() { - if err = recover(); err != nil { - ret = items[i].Name < items[j].Name - } - }() - ret = reflect.ValueOf(ii).String() < reflect.ValueOf(ij).String() - } - }() - return reflect.ValueOf(ii).Int() < reflect.ValueOf(ij).Int() - } - return true - } else if okj { - return false - } - return items[i].Name < items[j].Name -} - -// SchemaProperties is a map representing the properties of a Schema object. -// It knows how to transform its keys into an ordered slice. -type SchemaProperties map[string]Schema - -// ToOrderedSchemaItems transforms the map of properties into a sortable slice -func (properties SchemaProperties) ToOrderedSchemaItems() OrderSchemaItems { - items := make(OrderSchemaItems, 0, len(properties)) - for k, v := range properties { - items = append(items, OrderSchemaItem{ - Name: k, - Schema: v, - }) - } - sort.Sort(items) - return items -} - -// MarshalJSON produces properties as json, keeping their order. -func (properties SchemaProperties) MarshalJSON() ([]byte, error) { - if properties == nil { - return []byte("null"), nil - } - return json.Marshal(properties.ToOrderedSchemaItems()) -} diff --git a/vendor/github.com/go-openapi/spec/ref.go b/vendor/github.com/go-openapi/spec/ref.go deleted file mode 100644 index b0ef9bd9c..000000000 --- a/vendor/github.com/go-openapi/spec/ref.go +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "bytes" - "encoding/gob" - "encoding/json" - "net/http" - "os" - "path/filepath" - - "github.com/go-openapi/jsonreference" -) - -// Refable is a struct for things that accept a $ref property -type Refable struct { - Ref Ref -} - -// MarshalJSON marshals the ref to json -func (r Refable) MarshalJSON() ([]byte, error) { - return r.Ref.MarshalJSON() -} - -// UnmarshalJSON unmarshalss the ref from json -func (r *Refable) UnmarshalJSON(d []byte) error { - return json.Unmarshal(d, &r.Ref) -} - -// Ref represents a json reference that is potentially resolved -type Ref struct { - jsonreference.Ref -} - -// RemoteURI gets the remote uri part of the ref -func (r *Ref) RemoteURI() string { - if r.String() == "" { - return "" - } - - u := *r.GetURL() - u.Fragment = "" - return u.String() -} - -// IsValidURI returns true when the url the ref points to can be found -func (r *Ref) IsValidURI(basepaths ...string) bool { - if r.String() == "" { - return true - } - - v := r.RemoteURI() - if v == "" { - return true - } - - if r.HasFullURL { - //nolint:noctx,gosec - rr, err := http.Get(v) - if err != nil { - return false - } - defer rr.Body.Close() - - return rr.StatusCode/100 == 2 - } - - if !(r.HasFileScheme || r.HasFullFilePath || r.HasURLPathOnly) { - return false - } - - // check for local file - pth := v - if r.HasURLPathOnly { - base := "." - if len(basepaths) > 0 { - base = filepath.Dir(filepath.Join(basepaths...)) - } - p, e := filepath.Abs(filepath.ToSlash(filepath.Join(base, pth))) - if e != nil { - return false - } - pth = p - } - - fi, err := os.Stat(filepath.ToSlash(pth)) - if err != nil { - return false - } - - return !fi.IsDir() -} - -// Inherits creates a new reference from a parent and a child -// If the child cannot inherit from the parent, an error is returned -func (r *Ref) Inherits(child Ref) (*Ref, error) { - ref, err := r.Ref.Inherits(child.Ref) - if err != nil { - return nil, err - } - return &Ref{Ref: *ref}, nil -} - -// NewRef creates a new instance of a ref object -// returns an error when the reference uri is an invalid uri -func NewRef(refURI string) (Ref, error) { - ref, err := jsonreference.New(refURI) - if err != nil { - return Ref{}, err - } - return Ref{Ref: ref}, nil -} - -// MustCreateRef creates a ref object but panics when refURI is invalid. -// Use the NewRef method for a version that returns an error. -func MustCreateRef(refURI string) Ref { - return Ref{Ref: jsonreference.MustCreateRef(refURI)} -} - -// MarshalJSON marshals this ref into a JSON object -func (r Ref) MarshalJSON() ([]byte, error) { - str := r.String() - if str == "" { - if r.IsRoot() { - return []byte(`{"$ref":""}`), nil - } - return []byte("{}"), nil - } - v := map[string]interface{}{"$ref": str} - return json.Marshal(v) -} - -// UnmarshalJSON unmarshals this ref from a JSON object -func (r *Ref) UnmarshalJSON(d []byte) error { - var v map[string]interface{} - if err := json.Unmarshal(d, &v); err != nil { - return err - } - return r.fromMap(v) -} - -// GobEncode provides a safe gob encoder for Ref -func (r Ref) GobEncode() ([]byte, error) { - var b bytes.Buffer - raw, err := r.MarshalJSON() - if err != nil { - return nil, err - } - err = gob.NewEncoder(&b).Encode(raw) - return b.Bytes(), err -} - -// GobDecode provides a safe gob decoder for Ref -func (r *Ref) GobDecode(b []byte) error { - var raw []byte - buf := bytes.NewBuffer(b) - err := gob.NewDecoder(buf).Decode(&raw) - if err != nil { - return err - } - return json.Unmarshal(raw, r) -} - -func (r *Ref) fromMap(v map[string]interface{}) error { - if v == nil { - return nil - } - - if vv, ok := v["$ref"]; ok { - if str, ok := vv.(string); ok { - ref, err := jsonreference.New(str) - if err != nil { - return err - } - *r = Ref{Ref: ref} - } - } - - return nil -} diff --git a/vendor/github.com/go-openapi/spec/resolver.go b/vendor/github.com/go-openapi/spec/resolver.go deleted file mode 100644 index 47d1ee13f..000000000 --- a/vendor/github.com/go-openapi/spec/resolver.go +++ /dev/null @@ -1,127 +0,0 @@ -package spec - -import ( - "fmt" - - "github.com/go-openapi/swag" -) - -func resolveAnyWithBase(root interface{}, ref *Ref, result interface{}, options *ExpandOptions) error { - options = optionsOrDefault(options) - resolver := defaultSchemaLoader(root, options, nil, nil) - - if err := resolver.Resolve(ref, result, options.RelativeBase); err != nil { - return err - } - - return nil -} - -// ResolveRefWithBase resolves a reference against a context root with preservation of base path -func ResolveRefWithBase(root interface{}, ref *Ref, options *ExpandOptions) (*Schema, error) { - result := new(Schema) - - if err := resolveAnyWithBase(root, ref, result, options); err != nil { - return nil, err - } - - return result, nil -} - -// ResolveRef resolves a reference for a schema against a context root -// ref is guaranteed to be in root (no need to go to external files) -// -// ResolveRef is ONLY called from the code generation module -func ResolveRef(root interface{}, ref *Ref) (*Schema, error) { - res, _, err := ref.GetPointer().Get(root) - if err != nil { - return nil, err - } - - switch sch := res.(type) { - case Schema: - return &sch, nil - case *Schema: - return sch, nil - case map[string]interface{}: - newSch := new(Schema) - if err = swag.DynamicJSONToStruct(sch, newSch); err != nil { - return nil, err - } - return newSch, nil - default: - return nil, fmt.Errorf("type: %T: %w", sch, ErrUnknownTypeForReference) - } -} - -// ResolveParameterWithBase resolves a parameter reference against a context root and base path -func ResolveParameterWithBase(root interface{}, ref Ref, options *ExpandOptions) (*Parameter, error) { - result := new(Parameter) - - if err := resolveAnyWithBase(root, &ref, result, options); err != nil { - return nil, err - } - - return result, nil -} - -// ResolveParameter resolves a parameter reference against a context root -func ResolveParameter(root interface{}, ref Ref) (*Parameter, error) { - return ResolveParameterWithBase(root, ref, nil) -} - -// ResolveResponseWithBase resolves response a reference against a context root and base path -func ResolveResponseWithBase(root interface{}, ref Ref, options *ExpandOptions) (*Response, error) { - result := new(Response) - - err := resolveAnyWithBase(root, &ref, result, options) - if err != nil { - return nil, err - } - - return result, nil -} - -// ResolveResponse resolves response a reference against a context root -func ResolveResponse(root interface{}, ref Ref) (*Response, error) { - return ResolveResponseWithBase(root, ref, nil) -} - -// ResolvePathItemWithBase resolves response a path item against a context root and base path -func ResolvePathItemWithBase(root interface{}, ref Ref, options *ExpandOptions) (*PathItem, error) { - result := new(PathItem) - - if err := resolveAnyWithBase(root, &ref, result, options); err != nil { - return nil, err - } - - return result, nil -} - -// ResolvePathItem resolves response a path item against a context root and base path -// -// Deprecated: use ResolvePathItemWithBase instead -func ResolvePathItem(root interface{}, ref Ref, options *ExpandOptions) (*PathItem, error) { - return ResolvePathItemWithBase(root, ref, options) -} - -// ResolveItemsWithBase resolves parameter items reference against a context root and base path. -// -// NOTE: stricly speaking, this construct is not supported by Swagger 2.0. -// Similarly, $ref are forbidden in response headers. -func ResolveItemsWithBase(root interface{}, ref Ref, options *ExpandOptions) (*Items, error) { - result := new(Items) - - if err := resolveAnyWithBase(root, &ref, result, options); err != nil { - return nil, err - } - - return result, nil -} - -// ResolveItems resolves parameter items reference against a context root and base path. -// -// Deprecated: use ResolveItemsWithBase instead -func ResolveItems(root interface{}, ref Ref, options *ExpandOptions) (*Items, error) { - return ResolveItemsWithBase(root, ref, options) -} diff --git a/vendor/github.com/go-openapi/spec/response.go b/vendor/github.com/go-openapi/spec/response.go deleted file mode 100644 index 0340b60d8..000000000 --- a/vendor/github.com/go-openapi/spec/response.go +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "encoding/json" - - "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" -) - -// ResponseProps properties specific to a response -type ResponseProps struct { - Description string `json:"description"` - Schema *Schema `json:"schema,omitempty"` - Headers map[string]Header `json:"headers,omitempty"` - Examples map[string]interface{} `json:"examples,omitempty"` -} - -// Response describes a single response from an API Operation. -// -// For more information: http://goo.gl/8us55a#responseObject -type Response struct { - Refable - ResponseProps - VendorExtensible -} - -// JSONLookup look up a value by the json property name -func (r Response) JSONLookup(token string) (interface{}, error) { - if ex, ok := r.Extensions[token]; ok { - return &ex, nil - } - if token == "$ref" { - return &r.Ref, nil - } - ptr, _, err := jsonpointer.GetForToken(r.ResponseProps, token) - return ptr, err -} - -// UnmarshalJSON hydrates this items instance with the data from JSON -func (r *Response) UnmarshalJSON(data []byte) error { - if err := json.Unmarshal(data, &r.ResponseProps); err != nil { - return err - } - if err := json.Unmarshal(data, &r.Refable); err != nil { - return err - } - return json.Unmarshal(data, &r.VendorExtensible) -} - -// MarshalJSON converts this items object to JSON -func (r Response) MarshalJSON() ([]byte, error) { - var ( - b1 []byte - err error - ) - - if r.Ref.String() == "" { - // when there is no $ref, empty description is rendered as an empty string - b1, err = json.Marshal(r.ResponseProps) - } else { - // when there is $ref inside the schema, description should be omitempty-ied - b1, err = json.Marshal(struct { - Description string `json:"description,omitempty"` - Schema *Schema `json:"schema,omitempty"` - Headers map[string]Header `json:"headers,omitempty"` - Examples map[string]interface{} `json:"examples,omitempty"` - }{ - Description: r.ResponseProps.Description, - Schema: r.ResponseProps.Schema, - Examples: r.ResponseProps.Examples, - }) - } - if err != nil { - return nil, err - } - - b2, err := json.Marshal(r.Refable) - if err != nil { - return nil, err - } - b3, err := json.Marshal(r.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2, b3), nil -} - -// NewResponse creates a new response instance -func NewResponse() *Response { - return new(Response) -} - -// ResponseRef creates a response as a json reference -func ResponseRef(url string) *Response { - resp := NewResponse() - resp.Ref = MustCreateRef(url) - return resp -} - -// WithDescription sets the description on this response, allows for chaining -func (r *Response) WithDescription(description string) *Response { - r.Description = description - return r -} - -// WithSchema sets the schema on this response, allows for chaining. -// Passing a nil argument removes the schema from this response -func (r *Response) WithSchema(schema *Schema) *Response { - r.Schema = schema - return r -} - -// AddHeader adds a header to this response -func (r *Response) AddHeader(name string, header *Header) *Response { - if header == nil { - return r.RemoveHeader(name) - } - if r.Headers == nil { - r.Headers = make(map[string]Header) - } - r.Headers[name] = *header - return r -} - -// RemoveHeader removes a header from this response -func (r *Response) RemoveHeader(name string) *Response { - delete(r.Headers, name) - return r -} - -// AddExample adds an example to this response -func (r *Response) AddExample(mediaType string, example interface{}) *Response { - if r.Examples == nil { - r.Examples = make(map[string]interface{}) - } - r.Examples[mediaType] = example - return r -} diff --git a/vendor/github.com/go-openapi/spec/responses.go b/vendor/github.com/go-openapi/spec/responses.go deleted file mode 100644 index 4efb6f868..000000000 --- a/vendor/github.com/go-openapi/spec/responses.go +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "encoding/json" - "fmt" - "reflect" - "strconv" - - "github.com/go-openapi/swag" -) - -// Responses is a container for the expected responses of an operation. -// The container maps a HTTP response code to the expected response. -// It is not expected from the documentation to necessarily cover all possible HTTP response codes, -// since they may not be known in advance. However, it is expected from the documentation to cover -// a successful operation response and any known errors. -// -// The `default` can be used a default response object for all HTTP codes that are not covered -// individually by the specification. -// -// The `Responses Object` MUST contain at least one response code, and it SHOULD be the response -// for a successful operation call. -// -// For more information: http://goo.gl/8us55a#responsesObject -type Responses struct { - VendorExtensible - ResponsesProps -} - -// JSONLookup implements an interface to customize json pointer lookup -func (r Responses) JSONLookup(token string) (interface{}, error) { - if token == "default" { - return r.Default, nil - } - if ex, ok := r.Extensions[token]; ok { - return &ex, nil - } - if i, err := strconv.Atoi(token); err == nil { - if scr, ok := r.StatusCodeResponses[i]; ok { - return scr, nil - } - } - return nil, fmt.Errorf("object has no field %q", token) -} - -// UnmarshalJSON hydrates this items instance with the data from JSON -func (r *Responses) UnmarshalJSON(data []byte) error { - if err := json.Unmarshal(data, &r.ResponsesProps); err != nil { - return err - } - if err := json.Unmarshal(data, &r.VendorExtensible); err != nil { - return err - } - if reflect.DeepEqual(ResponsesProps{}, r.ResponsesProps) { - r.ResponsesProps = ResponsesProps{} - } - return nil -} - -// MarshalJSON converts this items object to JSON -func (r Responses) MarshalJSON() ([]byte, error) { - b1, err := json.Marshal(r.ResponsesProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(r.VendorExtensible) - if err != nil { - return nil, err - } - concated := swag.ConcatJSON(b1, b2) - return concated, nil -} - -// ResponsesProps describes all responses for an operation. -// It tells what is the default response and maps all responses with a -// HTTP status code. -type ResponsesProps struct { - Default *Response - StatusCodeResponses map[int]Response -} - -// MarshalJSON marshals responses as JSON -func (r ResponsesProps) MarshalJSON() ([]byte, error) { - toser := map[string]Response{} - if r.Default != nil { - toser["default"] = *r.Default - } - for k, v := range r.StatusCodeResponses { - toser[strconv.Itoa(k)] = v - } - return json.Marshal(toser) -} - -// UnmarshalJSON unmarshals responses from JSON -func (r *ResponsesProps) UnmarshalJSON(data []byte) error { - var res map[string]Response - if err := json.Unmarshal(data, &res); err != nil { - return nil - } - if v, ok := res["default"]; ok { - r.Default = &v - delete(res, "default") - } - for k, v := range res { - if nk, err := strconv.Atoi(k); err == nil { - if r.StatusCodeResponses == nil { - r.StatusCodeResponses = map[int]Response{} - } - r.StatusCodeResponses[nk] = v - } - } - return nil -} diff --git a/vendor/github.com/go-openapi/spec/schema.go b/vendor/github.com/go-openapi/spec/schema.go deleted file mode 100644 index a8d0f737a..000000000 --- a/vendor/github.com/go-openapi/spec/schema.go +++ /dev/null @@ -1,646 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "encoding/json" - "fmt" - "net/url" - "strings" - - "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" -) - -// BooleanProperty creates a boolean property -func BooleanProperty() *Schema { - return &Schema{SchemaProps: SchemaProps{Type: []string{"boolean"}}} -} - -// BoolProperty creates a boolean property -func BoolProperty() *Schema { return BooleanProperty() } - -// StringProperty creates a string property -func StringProperty() *Schema { - return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}}} -} - -// CharProperty creates a string property -func CharProperty() *Schema { - return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}}} -} - -// Float64Property creates a float64/double property -func Float64Property() *Schema { - return &Schema{SchemaProps: SchemaProps{Type: []string{"number"}, Format: "double"}} -} - -// Float32Property creates a float32/float property -func Float32Property() *Schema { - return &Schema{SchemaProps: SchemaProps{Type: []string{"number"}, Format: "float"}} -} - -// Int8Property creates an int8 property -func Int8Property() *Schema { - return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int8"}} -} - -// Int16Property creates an int16 property -func Int16Property() *Schema { - return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int16"}} -} - -// Int32Property creates an int32 property -func Int32Property() *Schema { - return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int32"}} -} - -// Int64Property creates an int64 property -func Int64Property() *Schema { - return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int64"}} -} - -// StrFmtProperty creates a property for the named string format -func StrFmtProperty(format string) *Schema { - return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}, Format: format}} -} - -// DateProperty creates a date property -func DateProperty() *Schema { - return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}, Format: "date"}} -} - -// DateTimeProperty creates a date time property -func DateTimeProperty() *Schema { - return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}, Format: "date-time"}} -} - -// MapProperty creates a map property -func MapProperty(property *Schema) *Schema { - return &Schema{SchemaProps: SchemaProps{Type: []string{"object"}, - AdditionalProperties: &SchemaOrBool{Allows: true, Schema: property}}} -} - -// RefProperty creates a ref property -func RefProperty(name string) *Schema { - return &Schema{SchemaProps: SchemaProps{Ref: MustCreateRef(name)}} -} - -// RefSchema creates a ref property -func RefSchema(name string) *Schema { - return &Schema{SchemaProps: SchemaProps{Ref: MustCreateRef(name)}} -} - -// ArrayProperty creates an array property -func ArrayProperty(items *Schema) *Schema { - if items == nil { - return &Schema{SchemaProps: SchemaProps{Type: []string{"array"}}} - } - return &Schema{SchemaProps: SchemaProps{Items: &SchemaOrArray{Schema: items}, Type: []string{"array"}}} -} - -// ComposedSchema creates a schema with allOf -func ComposedSchema(schemas ...Schema) *Schema { - s := new(Schema) - s.AllOf = schemas - return s -} - -// SchemaURL represents a schema url -type SchemaURL string - -// MarshalJSON marshal this to JSON -func (r SchemaURL) MarshalJSON() ([]byte, error) { - if r == "" { - return []byte("{}"), nil - } - v := map[string]interface{}{"$schema": string(r)} - return json.Marshal(v) -} - -// UnmarshalJSON unmarshal this from JSON -func (r *SchemaURL) UnmarshalJSON(data []byte) error { - var v map[string]interface{} - if err := json.Unmarshal(data, &v); err != nil { - return err - } - return r.fromMap(v) -} - -func (r *SchemaURL) fromMap(v map[string]interface{}) error { - if v == nil { - return nil - } - if vv, ok := v["$schema"]; ok { - if str, ok := vv.(string); ok { - u, err := url.Parse(str) - if err != nil { - return err - } - - *r = SchemaURL(u.String()) - } - } - return nil -} - -// SchemaProps describes a JSON schema (draft 4) -type SchemaProps struct { - ID string `json:"id,omitempty"` - Ref Ref `json:"-"` - Schema SchemaURL `json:"-"` - Description string `json:"description,omitempty"` - Type StringOrArray `json:"type,omitempty"` - Nullable bool `json:"nullable,omitempty"` - Format string `json:"format,omitempty"` - Title string `json:"title,omitempty"` - Default interface{} `json:"default,omitempty"` - Maximum *float64 `json:"maximum,omitempty"` - ExclusiveMaximum bool `json:"exclusiveMaximum,omitempty"` - Minimum *float64 `json:"minimum,omitempty"` - ExclusiveMinimum bool `json:"exclusiveMinimum,omitempty"` - MaxLength *int64 `json:"maxLength,omitempty"` - MinLength *int64 `json:"minLength,omitempty"` - Pattern string `json:"pattern,omitempty"` - MaxItems *int64 `json:"maxItems,omitempty"` - MinItems *int64 `json:"minItems,omitempty"` - UniqueItems bool `json:"uniqueItems,omitempty"` - MultipleOf *float64 `json:"multipleOf,omitempty"` - Enum []interface{} `json:"enum,omitempty"` - MaxProperties *int64 `json:"maxProperties,omitempty"` - MinProperties *int64 `json:"minProperties,omitempty"` - Required []string `json:"required,omitempty"` - Items *SchemaOrArray `json:"items,omitempty"` - AllOf []Schema `json:"allOf,omitempty"` - OneOf []Schema `json:"oneOf,omitempty"` - AnyOf []Schema `json:"anyOf,omitempty"` - Not *Schema `json:"not,omitempty"` - Properties SchemaProperties `json:"properties,omitempty"` - AdditionalProperties *SchemaOrBool `json:"additionalProperties,omitempty"` - PatternProperties SchemaProperties `json:"patternProperties,omitempty"` - Dependencies Dependencies `json:"dependencies,omitempty"` - AdditionalItems *SchemaOrBool `json:"additionalItems,omitempty"` - Definitions Definitions `json:"definitions,omitempty"` -} - -// SwaggerSchemaProps are additional properties supported by swagger schemas, but not JSON-schema (draft 4) -type SwaggerSchemaProps struct { - Discriminator string `json:"discriminator,omitempty"` - ReadOnly bool `json:"readOnly,omitempty"` - XML *XMLObject `json:"xml,omitempty"` - ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"` - Example interface{} `json:"example,omitempty"` -} - -// Schema the schema object allows the definition of input and output data types. -// These types can be objects, but also primitives and arrays. -// This object is based on the [JSON Schema Specification Draft 4](http://json-schema.org/) -// and uses a predefined subset of it. -// On top of this subset, there are extensions provided by this specification to allow for more complete documentation. -// -// For more information: http://goo.gl/8us55a#schemaObject -type Schema struct { - VendorExtensible - SchemaProps - SwaggerSchemaProps - ExtraProps map[string]interface{} `json:"-"` -} - -// JSONLookup implements an interface to customize json pointer lookup -func (s Schema) JSONLookup(token string) (interface{}, error) { - if ex, ok := s.Extensions[token]; ok { - return &ex, nil - } - - if ex, ok := s.ExtraProps[token]; ok { - return &ex, nil - } - - r, _, err := jsonpointer.GetForToken(s.SchemaProps, token) - if r != nil || (err != nil && !strings.HasPrefix(err.Error(), "object has no field")) { - return r, err - } - r, _, err = jsonpointer.GetForToken(s.SwaggerSchemaProps, token) - return r, err -} - -// WithID sets the id for this schema, allows for chaining -func (s *Schema) WithID(id string) *Schema { - s.ID = id - return s -} - -// WithTitle sets the title for this schema, allows for chaining -func (s *Schema) WithTitle(title string) *Schema { - s.Title = title - return s -} - -// WithDescription sets the description for this schema, allows for chaining -func (s *Schema) WithDescription(description string) *Schema { - s.Description = description - return s -} - -// WithProperties sets the properties for this schema -func (s *Schema) WithProperties(schemas map[string]Schema) *Schema { - s.Properties = schemas - return s -} - -// SetProperty sets a property on this schema -func (s *Schema) SetProperty(name string, schema Schema) *Schema { - if s.Properties == nil { - s.Properties = make(map[string]Schema) - } - s.Properties[name] = schema - return s -} - -// WithAllOf sets the all of property -func (s *Schema) WithAllOf(schemas ...Schema) *Schema { - s.AllOf = schemas - return s -} - -// WithMaxProperties sets the max number of properties an object can have -func (s *Schema) WithMaxProperties(max int64) *Schema { - s.MaxProperties = &max - return s -} - -// WithMinProperties sets the min number of properties an object must have -func (s *Schema) WithMinProperties(min int64) *Schema { - s.MinProperties = &min - return s -} - -// Typed sets the type of this schema for a single value item -func (s *Schema) Typed(tpe, format string) *Schema { - s.Type = []string{tpe} - s.Format = format - return s -} - -// AddType adds a type with potential format to the types for this schema -func (s *Schema) AddType(tpe, format string) *Schema { - s.Type = append(s.Type, tpe) - if format != "" { - s.Format = format - } - return s -} - -// AsNullable flags this schema as nullable. -func (s *Schema) AsNullable() *Schema { - s.Nullable = true - return s -} - -// CollectionOf a fluent builder method for an array parameter -func (s *Schema) CollectionOf(items Schema) *Schema { - s.Type = []string{jsonArray} - s.Items = &SchemaOrArray{Schema: &items} - return s -} - -// WithDefault sets the default value on this parameter -func (s *Schema) WithDefault(defaultValue interface{}) *Schema { - s.Default = defaultValue - return s -} - -// WithRequired flags this parameter as required -func (s *Schema) WithRequired(items ...string) *Schema { - s.Required = items - return s -} - -// AddRequired adds field names to the required properties array -func (s *Schema) AddRequired(items ...string) *Schema { - s.Required = append(s.Required, items...) - return s -} - -// WithMaxLength sets a max length value -func (s *Schema) WithMaxLength(max int64) *Schema { - s.MaxLength = &max - return s -} - -// WithMinLength sets a min length value -func (s *Schema) WithMinLength(min int64) *Schema { - s.MinLength = &min - return s -} - -// WithPattern sets a pattern value -func (s *Schema) WithPattern(pattern string) *Schema { - s.Pattern = pattern - return s -} - -// WithMultipleOf sets a multiple of value -func (s *Schema) WithMultipleOf(number float64) *Schema { - s.MultipleOf = &number - return s -} - -// WithMaximum sets a maximum number value -func (s *Schema) WithMaximum(max float64, exclusive bool) *Schema { - s.Maximum = &max - s.ExclusiveMaximum = exclusive - return s -} - -// WithMinimum sets a minimum number value -func (s *Schema) WithMinimum(min float64, exclusive bool) *Schema { - s.Minimum = &min - s.ExclusiveMinimum = exclusive - return s -} - -// WithEnum sets a the enum values (replace) -func (s *Schema) WithEnum(values ...interface{}) *Schema { - s.Enum = append([]interface{}{}, values...) - return s -} - -// WithMaxItems sets the max items -func (s *Schema) WithMaxItems(size int64) *Schema { - s.MaxItems = &size - return s -} - -// WithMinItems sets the min items -func (s *Schema) WithMinItems(size int64) *Schema { - s.MinItems = &size - return s -} - -// UniqueValues dictates that this array can only have unique items -func (s *Schema) UniqueValues() *Schema { - s.UniqueItems = true - return s -} - -// AllowDuplicates this array can have duplicates -func (s *Schema) AllowDuplicates() *Schema { - s.UniqueItems = false - return s -} - -// AddToAllOf adds a schema to the allOf property -func (s *Schema) AddToAllOf(schemas ...Schema) *Schema { - s.AllOf = append(s.AllOf, schemas...) - return s -} - -// WithDiscriminator sets the name of the discriminator field -func (s *Schema) WithDiscriminator(discriminator string) *Schema { - s.Discriminator = discriminator - return s -} - -// AsReadOnly flags this schema as readonly -func (s *Schema) AsReadOnly() *Schema { - s.ReadOnly = true - return s -} - -// AsWritable flags this schema as writeable (not read-only) -func (s *Schema) AsWritable() *Schema { - s.ReadOnly = false - return s -} - -// WithExample sets the example for this schema -func (s *Schema) WithExample(example interface{}) *Schema { - s.Example = example - return s -} - -// WithExternalDocs sets/removes the external docs for/from this schema. -// When you pass empty strings as params the external documents will be removed. -// When you pass non-empty string as one value then those values will be used on the external docs object. -// So when you pass a non-empty description, you should also pass the url and vice versa. -func (s *Schema) WithExternalDocs(description, url string) *Schema { - if description == "" && url == "" { - s.ExternalDocs = nil - return s - } - - if s.ExternalDocs == nil { - s.ExternalDocs = &ExternalDocumentation{} - } - s.ExternalDocs.Description = description - s.ExternalDocs.URL = url - return s -} - -// WithXMLName sets the xml name for the object -func (s *Schema) WithXMLName(name string) *Schema { - if s.XML == nil { - s.XML = new(XMLObject) - } - s.XML.Name = name - return s -} - -// WithXMLNamespace sets the xml namespace for the object -func (s *Schema) WithXMLNamespace(namespace string) *Schema { - if s.XML == nil { - s.XML = new(XMLObject) - } - s.XML.Namespace = namespace - return s -} - -// WithXMLPrefix sets the xml prefix for the object -func (s *Schema) WithXMLPrefix(prefix string) *Schema { - if s.XML == nil { - s.XML = new(XMLObject) - } - s.XML.Prefix = prefix - return s -} - -// AsXMLAttribute flags this object as xml attribute -func (s *Schema) AsXMLAttribute() *Schema { - if s.XML == nil { - s.XML = new(XMLObject) - } - s.XML.Attribute = true - return s -} - -// AsXMLElement flags this object as an xml node -func (s *Schema) AsXMLElement() *Schema { - if s.XML == nil { - s.XML = new(XMLObject) - } - s.XML.Attribute = false - return s -} - -// AsWrappedXML flags this object as wrapped, this is mostly useful for array types -func (s *Schema) AsWrappedXML() *Schema { - if s.XML == nil { - s.XML = new(XMLObject) - } - s.XML.Wrapped = true - return s -} - -// AsUnwrappedXML flags this object as an xml node -func (s *Schema) AsUnwrappedXML() *Schema { - if s.XML == nil { - s.XML = new(XMLObject) - } - s.XML.Wrapped = false - return s -} - -// SetValidations defines all schema validations. -// -// NOTE: Required, ReadOnly, AllOf, AnyOf, OneOf and Not are not considered. -func (s *Schema) SetValidations(val SchemaValidations) { - s.Maximum = val.Maximum - s.ExclusiveMaximum = val.ExclusiveMaximum - s.Minimum = val.Minimum - s.ExclusiveMinimum = val.ExclusiveMinimum - s.MaxLength = val.MaxLength - s.MinLength = val.MinLength - s.Pattern = val.Pattern - s.MaxItems = val.MaxItems - s.MinItems = val.MinItems - s.UniqueItems = val.UniqueItems - s.MultipleOf = val.MultipleOf - s.Enum = val.Enum - s.MinProperties = val.MinProperties - s.MaxProperties = val.MaxProperties - s.PatternProperties = val.PatternProperties -} - -// WithValidations is a fluent method to set schema validations -func (s *Schema) WithValidations(val SchemaValidations) *Schema { - s.SetValidations(val) - return s -} - -// Validations returns a clone of the validations for this schema -func (s Schema) Validations() SchemaValidations { - return SchemaValidations{ - CommonValidations: CommonValidations{ - Maximum: s.Maximum, - ExclusiveMaximum: s.ExclusiveMaximum, - Minimum: s.Minimum, - ExclusiveMinimum: s.ExclusiveMinimum, - MaxLength: s.MaxLength, - MinLength: s.MinLength, - Pattern: s.Pattern, - MaxItems: s.MaxItems, - MinItems: s.MinItems, - UniqueItems: s.UniqueItems, - MultipleOf: s.MultipleOf, - Enum: s.Enum, - }, - MinProperties: s.MinProperties, - MaxProperties: s.MaxProperties, - PatternProperties: s.PatternProperties, - } -} - -// MarshalJSON marshal this to JSON -func (s Schema) MarshalJSON() ([]byte, error) { - b1, err := json.Marshal(s.SchemaProps) - if err != nil { - return nil, fmt.Errorf("schema props %v", err) - } - b2, err := json.Marshal(s.VendorExtensible) - if err != nil { - return nil, fmt.Errorf("vendor props %v", err) - } - b3, err := s.Ref.MarshalJSON() - if err != nil { - return nil, fmt.Errorf("ref prop %v", err) - } - b4, err := s.Schema.MarshalJSON() - if err != nil { - return nil, fmt.Errorf("schema prop %v", err) - } - b5, err := json.Marshal(s.SwaggerSchemaProps) - if err != nil { - return nil, fmt.Errorf("common validations %v", err) - } - var b6 []byte - if s.ExtraProps != nil { - jj, err := json.Marshal(s.ExtraProps) - if err != nil { - return nil, fmt.Errorf("extra props %v", err) - } - b6 = jj - } - return swag.ConcatJSON(b1, b2, b3, b4, b5, b6), nil -} - -// UnmarshalJSON marshal this from JSON -func (s *Schema) UnmarshalJSON(data []byte) error { - props := struct { - SchemaProps - SwaggerSchemaProps - }{} - if err := json.Unmarshal(data, &props); err != nil { - return err - } - - sch := Schema{ - SchemaProps: props.SchemaProps, - SwaggerSchemaProps: props.SwaggerSchemaProps, - } - - var d map[string]interface{} - if err := json.Unmarshal(data, &d); err != nil { - return err - } - - _ = sch.Ref.fromMap(d) - _ = sch.Schema.fromMap(d) - - delete(d, "$ref") - delete(d, "$schema") - for _, pn := range swag.DefaultJSONNameProvider.GetJSONNames(s) { - delete(d, pn) - } - - for k, vv := range d { - lk := strings.ToLower(k) - if strings.HasPrefix(lk, "x-") { - if sch.Extensions == nil { - sch.Extensions = map[string]interface{}{} - } - sch.Extensions[k] = vv - continue - } - if sch.ExtraProps == nil { - sch.ExtraProps = map[string]interface{}{} - } - sch.ExtraProps[k] = vv - } - - *s = sch - - return nil -} diff --git a/vendor/github.com/go-openapi/spec/schema_loader.go b/vendor/github.com/go-openapi/spec/schema_loader.go deleted file mode 100644 index b81175afd..000000000 --- a/vendor/github.com/go-openapi/spec/schema_loader.go +++ /dev/null @@ -1,338 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "encoding/json" - "fmt" - "log" - "net/url" - "reflect" - "strings" - - "github.com/go-openapi/swag" -) - -// PathLoader is a function to use when loading remote refs. -// -// This is a package level default. It may be overridden or bypassed by -// specifying the loader in ExpandOptions. -// -// NOTE: if you are using the go-openapi/loads package, it will override -// this value with its own default (a loader to retrieve YAML documents as -// well as JSON ones). -var PathLoader = func(pth string) (json.RawMessage, error) { - data, err := swag.LoadFromFileOrHTTP(pth) - if err != nil { - return nil, err - } - return json.RawMessage(data), nil -} - -// resolverContext allows to share a context during spec processing. -// At the moment, it just holds the index of circular references found. -type resolverContext struct { - // circulars holds all visited circular references, to shortcircuit $ref resolution. - // - // This structure is privately instantiated and needs not be locked against - // concurrent access, unless we chose to implement a parallel spec walking. - circulars map[string]bool - basePath string - loadDoc func(string) (json.RawMessage, error) - rootID string -} - -func newResolverContext(options *ExpandOptions) *resolverContext { - expandOptions := optionsOrDefault(options) - - // path loader may be overridden by options - var loader func(string) (json.RawMessage, error) - if expandOptions.PathLoader == nil { - loader = PathLoader - } else { - loader = expandOptions.PathLoader - } - - return &resolverContext{ - circulars: make(map[string]bool), - basePath: expandOptions.RelativeBase, // keep the root base path in context - loadDoc: loader, - } -} - -type schemaLoader struct { - root interface{} - options *ExpandOptions - cache ResolutionCache - context *resolverContext -} - -func (r *schemaLoader) transitiveResolver(basePath string, ref Ref) *schemaLoader { - if ref.IsRoot() || ref.HasFragmentOnly { - return r - } - - baseRef := MustCreateRef(basePath) - currentRef := normalizeRef(&ref, basePath) - if strings.HasPrefix(currentRef.String(), baseRef.String()) { - return r - } - - // set a new root against which to resolve - rootURL := currentRef.GetURL() - rootURL.Fragment = "" - root, _ := r.cache.Get(rootURL.String()) - - // shallow copy of resolver options to set a new RelativeBase when - // traversing multiple documents - newOptions := r.options - newOptions.RelativeBase = rootURL.String() - - return defaultSchemaLoader(root, newOptions, r.cache, r.context) -} - -func (r *schemaLoader) updateBasePath(transitive *schemaLoader, basePath string) string { - if transitive != r { - if transitive.options != nil && transitive.options.RelativeBase != "" { - return normalizeBase(transitive.options.RelativeBase) - } - } - - return basePath -} - -func (r *schemaLoader) resolveRef(ref *Ref, target interface{}, basePath string) error { - tgt := reflect.ValueOf(target) - if tgt.Kind() != reflect.Ptr { - return ErrResolveRefNeedsAPointer - } - - if ref.GetURL() == nil { - return nil - } - - var ( - res interface{} - data interface{} - err error - ) - - // Resolve against the root if it isn't nil, and if ref is pointing at the root, or has a fragment only which means - // it is pointing somewhere in the root. - root := r.root - if (ref.IsRoot() || ref.HasFragmentOnly) && root == nil && basePath != "" { - if baseRef, erb := NewRef(basePath); erb == nil { - root, _, _, _ = r.load(baseRef.GetURL()) - } - } - - if (ref.IsRoot() || ref.HasFragmentOnly) && root != nil { - data = root - } else { - baseRef := normalizeRef(ref, basePath) - data, _, _, err = r.load(baseRef.GetURL()) - if err != nil { - return err - } - } - - res = data - if ref.String() != "" { - res, _, err = ref.GetPointer().Get(data) - if err != nil { - return err - } - } - return swag.DynamicJSONToStruct(res, target) -} - -func (r *schemaLoader) load(refURL *url.URL) (interface{}, url.URL, bool, error) { - debugLog("loading schema from url: %s", refURL) - toFetch := *refURL - toFetch.Fragment = "" - - var err error - pth := toFetch.String() - normalized := normalizeBase(pth) - debugLog("loading doc from: %s", normalized) - - unescaped, err := url.PathUnescape(normalized) - if err != nil { - return nil, url.URL{}, false, err - } - - u := url.URL{Path: unescaped} - - data, fromCache := r.cache.Get(u.RequestURI()) - if fromCache { - return data, toFetch, fromCache, nil - } - - b, err := r.context.loadDoc(normalized) - if err != nil { - return nil, url.URL{}, false, err - } - - var doc interface{} - if err := json.Unmarshal(b, &doc); err != nil { - return nil, url.URL{}, false, err - } - r.cache.Set(normalized, doc) - - return doc, toFetch, fromCache, nil -} - -// isCircular detects cycles in sequences of $ref. -// -// It relies on a private context (which needs not be locked). -func (r *schemaLoader) isCircular(ref *Ref, basePath string, parentRefs ...string) (foundCycle bool) { - normalizedRef := normalizeURI(ref.String(), basePath) - if _, ok := r.context.circulars[normalizedRef]; ok { - // circular $ref has been already detected in another explored cycle - foundCycle = true - return - } - foundCycle = swag.ContainsStrings(parentRefs, normalizedRef) // normalized windows url's are lower cased - if foundCycle { - r.context.circulars[normalizedRef] = true - } - return -} - -// Resolve resolves a reference against basePath and stores the result in target. -// -// Resolve is not in charge of following references: it only resolves ref by following its URL. -// -// If the schema the ref is referring to holds nested refs, Resolve doesn't resolve them. -// -// If basePath is an empty string, ref is resolved against the root schema stored in the schemaLoader struct -func (r *schemaLoader) Resolve(ref *Ref, target interface{}, basePath string) error { - return r.resolveRef(ref, target, basePath) -} - -func (r *schemaLoader) deref(input interface{}, parentRefs []string, basePath string) error { - var ref *Ref - switch refable := input.(type) { - case *Schema: - ref = &refable.Ref - case *Parameter: - ref = &refable.Ref - case *Response: - ref = &refable.Ref - case *PathItem: - ref = &refable.Ref - default: - return fmt.Errorf("unsupported type: %T: %w", input, ErrDerefUnsupportedType) - } - - curRef := ref.String() - if curRef == "" { - return nil - } - - normalizedRef := normalizeRef(ref, basePath) - normalizedBasePath := normalizedRef.RemoteURI() - - if r.isCircular(normalizedRef, basePath, parentRefs...) { - return nil - } - - if err := r.resolveRef(ref, input, basePath); r.shouldStopOnError(err) { - return err - } - - if ref.String() == "" || ref.String() == curRef { - // done with rereferencing - return nil - } - - parentRefs = append(parentRefs, normalizedRef.String()) - return r.deref(input, parentRefs, normalizedBasePath) -} - -func (r *schemaLoader) shouldStopOnError(err error) bool { - if err != nil && !r.options.ContinueOnError { - return true - } - - if err != nil { - log.Println(err) - } - - return false -} - -func (r *schemaLoader) setSchemaID(target interface{}, id, basePath string) (string, string) { - debugLog("schema has ID: %s", id) - - // handling the case when id is a folder - // remember that basePath has to point to a file - var refPath string - if strings.HasSuffix(id, "/") { - // ensure this is detected as a file, not a folder - refPath = fmt.Sprintf("%s%s", id, "placeholder.json") - } else { - refPath = id - } - - // updates the current base path - // * important: ID can be a relative path - // * registers target to be fetchable from the new base proposed by this id - newBasePath := normalizeURI(refPath, basePath) - - // store found IDs for possible future reuse in $ref - r.cache.Set(newBasePath, target) - - // the root document has an ID: all $ref relative to that ID may - // be rebased relative to the root document - if basePath == r.context.basePath { - debugLog("root document is a schema with ID: %s (normalized as:%s)", id, newBasePath) - r.context.rootID = newBasePath - } - - return newBasePath, refPath -} - -func defaultSchemaLoader( - root interface{}, - expandOptions *ExpandOptions, - cache ResolutionCache, - context *resolverContext) *schemaLoader { - - if expandOptions == nil { - expandOptions = &ExpandOptions{} - } - - cache = cacheOrDefault(cache) - - if expandOptions.RelativeBase == "" { - // if no relative base is provided, assume the root document - // contains all $ref, or at least, that the relative documents - // may be resolved from the current working directory. - expandOptions.RelativeBase = baseForRoot(root, cache) - } - debugLog("effective expander options: %#v", expandOptions) - - if context == nil { - context = newResolverContext(expandOptions) - } - - return &schemaLoader{ - root: root, - options: expandOptions, - cache: cache, - context: context, - } -} diff --git a/vendor/github.com/go-openapi/spec/security_scheme.go b/vendor/github.com/go-openapi/spec/security_scheme.go deleted file mode 100644 index 9d0bdae90..000000000 --- a/vendor/github.com/go-openapi/spec/security_scheme.go +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "encoding/json" - - "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" -) - -const ( - basic = "basic" - apiKey = "apiKey" - oauth2 = "oauth2" - implicit = "implicit" - password = "password" - application = "application" - accessCode = "accessCode" -) - -// BasicAuth creates a basic auth security scheme -func BasicAuth() *SecurityScheme { - return &SecurityScheme{SecuritySchemeProps: SecuritySchemeProps{Type: basic}} -} - -// APIKeyAuth creates an api key auth security scheme -func APIKeyAuth(fieldName, valueSource string) *SecurityScheme { - return &SecurityScheme{SecuritySchemeProps: SecuritySchemeProps{Type: apiKey, Name: fieldName, In: valueSource}} -} - -// OAuth2Implicit creates an implicit flow oauth2 security scheme -func OAuth2Implicit(authorizationURL string) *SecurityScheme { - return &SecurityScheme{SecuritySchemeProps: SecuritySchemeProps{ - Type: oauth2, - Flow: implicit, - AuthorizationURL: authorizationURL, - }} -} - -// OAuth2Password creates a password flow oauth2 security scheme -func OAuth2Password(tokenURL string) *SecurityScheme { - return &SecurityScheme{SecuritySchemeProps: SecuritySchemeProps{ - Type: oauth2, - Flow: password, - TokenURL: tokenURL, - }} -} - -// OAuth2Application creates an application flow oauth2 security scheme -func OAuth2Application(tokenURL string) *SecurityScheme { - return &SecurityScheme{SecuritySchemeProps: SecuritySchemeProps{ - Type: oauth2, - Flow: application, - TokenURL: tokenURL, - }} -} - -// OAuth2AccessToken creates an access token flow oauth2 security scheme -func OAuth2AccessToken(authorizationURL, tokenURL string) *SecurityScheme { - return &SecurityScheme{SecuritySchemeProps: SecuritySchemeProps{ - Type: oauth2, - Flow: accessCode, - AuthorizationURL: authorizationURL, - TokenURL: tokenURL, - }} -} - -// SecuritySchemeProps describes a swagger security scheme in the securityDefinitions section -type SecuritySchemeProps struct { - Description string `json:"description,omitempty"` - Type string `json:"type"` - Name string `json:"name,omitempty"` // api key - In string `json:"in,omitempty"` // api key - Flow string `json:"flow,omitempty"` // oauth2 - AuthorizationURL string `json:"authorizationUrl"` // oauth2 - TokenURL string `json:"tokenUrl,omitempty"` // oauth2 - Scopes map[string]string `json:"scopes,omitempty"` // oauth2 -} - -// AddScope adds a scope to this security scheme -func (s *SecuritySchemeProps) AddScope(scope, description string) { - if s.Scopes == nil { - s.Scopes = make(map[string]string) - } - s.Scopes[scope] = description -} - -// SecurityScheme allows the definition of a security scheme that can be used by the operations. -// Supported schemes are basic authentication, an API key (either as a header or as a query parameter) -// and OAuth2's common flows (implicit, password, application and access code). -// -// For more information: http://goo.gl/8us55a#securitySchemeObject -type SecurityScheme struct { - VendorExtensible - SecuritySchemeProps -} - -// JSONLookup implements an interface to customize json pointer lookup -func (s SecurityScheme) JSONLookup(token string) (interface{}, error) { - if ex, ok := s.Extensions[token]; ok { - return &ex, nil - } - - r, _, err := jsonpointer.GetForToken(s.SecuritySchemeProps, token) - return r, err -} - -// MarshalJSON marshal this to JSON -func (s SecurityScheme) MarshalJSON() ([]byte, error) { - var ( - b1 []byte - err error - ) - - if s.Type == oauth2 && (s.Flow == "implicit" || s.Flow == "accessCode") { - // when oauth2 for implicit or accessCode flows, empty AuthorizationURL is added as empty string - b1, err = json.Marshal(s.SecuritySchemeProps) - } else { - // when not oauth2, empty AuthorizationURL should be omitted - b1, err = json.Marshal(struct { - Description string `json:"description,omitempty"` - Type string `json:"type"` - Name string `json:"name,omitempty"` // api key - In string `json:"in,omitempty"` // api key - Flow string `json:"flow,omitempty"` // oauth2 - AuthorizationURL string `json:"authorizationUrl,omitempty"` // oauth2 - TokenURL string `json:"tokenUrl,omitempty"` // oauth2 - Scopes map[string]string `json:"scopes,omitempty"` // oauth2 - }{ - Description: s.Description, - Type: s.Type, - Name: s.Name, - In: s.In, - Flow: s.Flow, - AuthorizationURL: s.AuthorizationURL, - TokenURL: s.TokenURL, - Scopes: s.Scopes, - }) - } - if err != nil { - return nil, err - } - - b2, err := json.Marshal(s.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2), nil -} - -// UnmarshalJSON marshal this from JSON -func (s *SecurityScheme) UnmarshalJSON(data []byte) error { - if err := json.Unmarshal(data, &s.SecuritySchemeProps); err != nil { - return err - } - return json.Unmarshal(data, &s.VendorExtensible) -} diff --git a/vendor/github.com/go-openapi/spec/spec.go b/vendor/github.com/go-openapi/spec/spec.go deleted file mode 100644 index 7d38b6e62..000000000 --- a/vendor/github.com/go-openapi/spec/spec.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "encoding/json" -) - -//go:generate curl -L --progress -o ./schemas/v2/schema.json http://swagger.io/v2/schema.json -//go:generate curl -L --progress -o ./schemas/jsonschema-draft-04.json http://json-schema.org/draft-04/schema -//go:generate go-bindata -pkg=spec -prefix=./schemas -ignore=.*\.md ./schemas/... -//go:generate perl -pi -e s,Json,JSON,g bindata.go - -const ( - // SwaggerSchemaURL the url for the swagger 2.0 schema to validate specs - SwaggerSchemaURL = "http://swagger.io/v2/schema.json#" - // JSONSchemaURL the url for the json schema schema - JSONSchemaURL = "http://json-schema.org/draft-04/schema#" -) - -// MustLoadJSONSchemaDraft04 panics when Swagger20Schema returns an error -func MustLoadJSONSchemaDraft04() *Schema { - d, e := JSONSchemaDraft04() - if e != nil { - panic(e) - } - return d -} - -// JSONSchemaDraft04 loads the json schema document for json shema draft04 -func JSONSchemaDraft04() (*Schema, error) { - b, err := Asset("jsonschema-draft-04.json") - if err != nil { - return nil, err - } - - schema := new(Schema) - if err := json.Unmarshal(b, schema); err != nil { - return nil, err - } - return schema, nil -} - -// MustLoadSwagger20Schema panics when Swagger20Schema returns an error -func MustLoadSwagger20Schema() *Schema { - d, e := Swagger20Schema() - if e != nil { - panic(e) - } - return d -} - -// Swagger20Schema loads the swagger 2.0 schema from the embedded assets -func Swagger20Schema() (*Schema, error) { - - b, err := Asset("v2/schema.json") - if err != nil { - return nil, err - } - - schema := new(Schema) - if err := json.Unmarshal(b, schema); err != nil { - return nil, err - } - return schema, nil -} diff --git a/vendor/github.com/go-openapi/spec/swagger.go b/vendor/github.com/go-openapi/spec/swagger.go deleted file mode 100644 index 44722ffd5..000000000 --- a/vendor/github.com/go-openapi/spec/swagger.go +++ /dev/null @@ -1,448 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "bytes" - "encoding/gob" - "encoding/json" - "fmt" - "strconv" - - "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" -) - -// Swagger this is the root document object for the API specification. -// It combines what previously was the Resource Listing and API Declaration (version 1.2 and earlier) -// together into one document. -// -// For more information: http://goo.gl/8us55a#swagger-object- -type Swagger struct { - VendorExtensible - SwaggerProps -} - -// JSONLookup look up a value by the json property name -func (s Swagger) JSONLookup(token string) (interface{}, error) { - if ex, ok := s.Extensions[token]; ok { - return &ex, nil - } - r, _, err := jsonpointer.GetForToken(s.SwaggerProps, token) - return r, err -} - -// MarshalJSON marshals this swagger structure to json -func (s Swagger) MarshalJSON() ([]byte, error) { - b1, err := json.Marshal(s.SwaggerProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(s.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2), nil -} - -// UnmarshalJSON unmarshals a swagger spec from json -func (s *Swagger) UnmarshalJSON(data []byte) error { - var sw Swagger - if err := json.Unmarshal(data, &sw.SwaggerProps); err != nil { - return err - } - if err := json.Unmarshal(data, &sw.VendorExtensible); err != nil { - return err - } - *s = sw - return nil -} - -// GobEncode provides a safe gob encoder for Swagger, including extensions -func (s Swagger) GobEncode() ([]byte, error) { - var b bytes.Buffer - raw := struct { - Props SwaggerProps - Ext VendorExtensible - }{ - Props: s.SwaggerProps, - Ext: s.VendorExtensible, - } - err := gob.NewEncoder(&b).Encode(raw) - return b.Bytes(), err -} - -// GobDecode provides a safe gob decoder for Swagger, including extensions -func (s *Swagger) GobDecode(b []byte) error { - var raw struct { - Props SwaggerProps - Ext VendorExtensible - } - buf := bytes.NewBuffer(b) - err := gob.NewDecoder(buf).Decode(&raw) - if err != nil { - return err - } - s.SwaggerProps = raw.Props - s.VendorExtensible = raw.Ext - return nil -} - -// SwaggerProps captures the top-level properties of an Api specification -// -// NOTE: validation rules -// - the scheme, when present must be from [http, https, ws, wss] -// - BasePath must start with a leading "/" -// - Paths is required -type SwaggerProps struct { - ID string `json:"id,omitempty"` - Consumes []string `json:"consumes,omitempty"` - Produces []string `json:"produces,omitempty"` - Schemes []string `json:"schemes,omitempty"` - Swagger string `json:"swagger,omitempty"` - Info *Info `json:"info,omitempty"` - Host string `json:"host,omitempty"` - BasePath string `json:"basePath,omitempty"` - Paths *Paths `json:"paths"` - Definitions Definitions `json:"definitions,omitempty"` - Parameters map[string]Parameter `json:"parameters,omitempty"` - Responses map[string]Response `json:"responses,omitempty"` - SecurityDefinitions SecurityDefinitions `json:"securityDefinitions,omitempty"` - Security []map[string][]string `json:"security,omitempty"` - Tags []Tag `json:"tags,omitempty"` - ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"` -} - -type swaggerPropsAlias SwaggerProps - -type gobSwaggerPropsAlias struct { - Security []map[string]struct { - List []string - Pad bool - } - Alias *swaggerPropsAlias - SecurityIsEmpty bool -} - -// GobEncode provides a safe gob encoder for SwaggerProps, including empty security requirements -func (o SwaggerProps) GobEncode() ([]byte, error) { - raw := gobSwaggerPropsAlias{ - Alias: (*swaggerPropsAlias)(&o), - } - - var b bytes.Buffer - if o.Security == nil { - // nil security requirement - err := gob.NewEncoder(&b).Encode(raw) - return b.Bytes(), err - } - - if len(o.Security) == 0 { - // empty, but non-nil security requirement - raw.SecurityIsEmpty = true - raw.Alias.Security = nil - err := gob.NewEncoder(&b).Encode(raw) - return b.Bytes(), err - } - - raw.Security = make([]map[string]struct { - List []string - Pad bool - }, 0, len(o.Security)) - for _, req := range o.Security { - v := make(map[string]struct { - List []string - Pad bool - }, len(req)) - for k, val := range req { - v[k] = struct { - List []string - Pad bool - }{ - List: val, - } - } - raw.Security = append(raw.Security, v) - } - - err := gob.NewEncoder(&b).Encode(raw) - return b.Bytes(), err -} - -// GobDecode provides a safe gob decoder for SwaggerProps, including empty security requirements -func (o *SwaggerProps) GobDecode(b []byte) error { - var raw gobSwaggerPropsAlias - - buf := bytes.NewBuffer(b) - err := gob.NewDecoder(buf).Decode(&raw) - if err != nil { - return err - } - if raw.Alias == nil { - return nil - } - - switch { - case raw.SecurityIsEmpty: - // empty, but non-nil security requirement - raw.Alias.Security = []map[string][]string{} - case len(raw.Alias.Security) == 0: - // nil security requirement - raw.Alias.Security = nil - default: - raw.Alias.Security = make([]map[string][]string, 0, len(raw.Security)) - for _, req := range raw.Security { - v := make(map[string][]string, len(req)) - for k, val := range req { - v[k] = make([]string, 0, len(val.List)) - v[k] = append(v[k], val.List...) - } - raw.Alias.Security = append(raw.Alias.Security, v) - } - } - - *o = *(*SwaggerProps)(raw.Alias) - return nil -} - -// Dependencies represent a dependencies property -type Dependencies map[string]SchemaOrStringArray - -// SchemaOrBool represents a schema or boolean value, is biased towards true for the boolean property -type SchemaOrBool struct { - Allows bool - Schema *Schema -} - -// JSONLookup implements an interface to customize json pointer lookup -func (s SchemaOrBool) JSONLookup(token string) (interface{}, error) { - if token == "allows" { - return s.Allows, nil - } - r, _, err := jsonpointer.GetForToken(s.Schema, token) - return r, err -} - -var jsTrue = []byte("true") -var jsFalse = []byte("false") - -// MarshalJSON convert this object to JSON -func (s SchemaOrBool) MarshalJSON() ([]byte, error) { - if s.Schema != nil { - return json.Marshal(s.Schema) - } - - if s.Schema == nil && !s.Allows { - return jsFalse, nil - } - return jsTrue, nil -} - -// UnmarshalJSON converts this bool or schema object from a JSON structure -func (s *SchemaOrBool) UnmarshalJSON(data []byte) error { - var nw SchemaOrBool - if len(data) >= 4 { - if data[0] == '{' { - var sch Schema - if err := json.Unmarshal(data, &sch); err != nil { - return err - } - nw.Schema = &sch - } - nw.Allows = !(data[0] == 'f' && data[1] == 'a' && data[2] == 'l' && data[3] == 's' && data[4] == 'e') - } - *s = nw - return nil -} - -// SchemaOrStringArray represents a schema or a string array -type SchemaOrStringArray struct { - Schema *Schema - Property []string -} - -// JSONLookup implements an interface to customize json pointer lookup -func (s SchemaOrStringArray) JSONLookup(token string) (interface{}, error) { - r, _, err := jsonpointer.GetForToken(s.Schema, token) - return r, err -} - -// MarshalJSON converts this schema object or array into JSON structure -func (s SchemaOrStringArray) MarshalJSON() ([]byte, error) { - if len(s.Property) > 0 { - return json.Marshal(s.Property) - } - if s.Schema != nil { - return json.Marshal(s.Schema) - } - return []byte("null"), nil -} - -// UnmarshalJSON converts this schema object or array from a JSON structure -func (s *SchemaOrStringArray) UnmarshalJSON(data []byte) error { - var first byte - if len(data) > 1 { - first = data[0] - } - var nw SchemaOrStringArray - if first == '{' { - var sch Schema - if err := json.Unmarshal(data, &sch); err != nil { - return err - } - nw.Schema = &sch - } - if first == '[' { - if err := json.Unmarshal(data, &nw.Property); err != nil { - return err - } - } - *s = nw - return nil -} - -// Definitions contains the models explicitly defined in this spec -// An object to hold data types that can be consumed and produced by operations. -// These data types can be primitives, arrays or models. -// -// For more information: http://goo.gl/8us55a#definitionsObject -type Definitions map[string]Schema - -// SecurityDefinitions a declaration of the security schemes available to be used in the specification. -// This does not enforce the security schemes on the operations and only serves to provide -// the relevant details for each scheme. -// -// For more information: http://goo.gl/8us55a#securityDefinitionsObject -type SecurityDefinitions map[string]*SecurityScheme - -// StringOrArray represents a value that can either be a string -// or an array of strings. Mainly here for serialization purposes -type StringOrArray []string - -// Contains returns true when the value is contained in the slice -func (s StringOrArray) Contains(value string) bool { - for _, str := range s { - if str == value { - return true - } - } - return false -} - -// JSONLookup implements an interface to customize json pointer lookup -func (s SchemaOrArray) JSONLookup(token string) (interface{}, error) { - if _, err := strconv.Atoi(token); err == nil { - r, _, err := jsonpointer.GetForToken(s.Schemas, token) - return r, err - } - r, _, err := jsonpointer.GetForToken(s.Schema, token) - return r, err -} - -// UnmarshalJSON unmarshals this string or array object from a JSON array or JSON string -func (s *StringOrArray) UnmarshalJSON(data []byte) error { - var first byte - if len(data) > 1 { - first = data[0] - } - - if first == '[' { - var parsed []string - if err := json.Unmarshal(data, &parsed); err != nil { - return err - } - *s = StringOrArray(parsed) - return nil - } - - var single interface{} - if err := json.Unmarshal(data, &single); err != nil { - return err - } - if single == nil { - return nil - } - switch v := single.(type) { - case string: - *s = StringOrArray([]string{v}) - return nil - default: - return fmt.Errorf("only string or array is allowed, not %T", single) - } -} - -// MarshalJSON converts this string or array to a JSON array or JSON string -func (s StringOrArray) MarshalJSON() ([]byte, error) { - if len(s) == 1 { - return json.Marshal([]string(s)[0]) - } - return json.Marshal([]string(s)) -} - -// SchemaOrArray represents a value that can either be a Schema -// or an array of Schema. Mainly here for serialization purposes -type SchemaOrArray struct { - Schema *Schema - Schemas []Schema -} - -// Len returns the number of schemas in this property -func (s SchemaOrArray) Len() int { - if s.Schema != nil { - return 1 - } - return len(s.Schemas) -} - -// ContainsType returns true when one of the schemas is of the specified type -func (s *SchemaOrArray) ContainsType(name string) bool { - if s.Schema != nil { - return s.Schema.Type != nil && s.Schema.Type.Contains(name) - } - return false -} - -// MarshalJSON converts this schema object or array into JSON structure -func (s SchemaOrArray) MarshalJSON() ([]byte, error) { - if len(s.Schemas) > 0 { - return json.Marshal(s.Schemas) - } - return json.Marshal(s.Schema) -} - -// UnmarshalJSON converts this schema object or array from a JSON structure -func (s *SchemaOrArray) UnmarshalJSON(data []byte) error { - var nw SchemaOrArray - var first byte - if len(data) > 1 { - first = data[0] - } - if first == '{' { - var sch Schema - if err := json.Unmarshal(data, &sch); err != nil { - return err - } - nw.Schema = &sch - } - if first == '[' { - if err := json.Unmarshal(data, &nw.Schemas); err != nil { - return err - } - } - *s = nw - return nil -} - -// vim:set ft=go noet sts=2 sw=2 ts=2: diff --git a/vendor/github.com/go-openapi/spec/tag.go b/vendor/github.com/go-openapi/spec/tag.go deleted file mode 100644 index faa3d3de1..000000000 --- a/vendor/github.com/go-openapi/spec/tag.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -import ( - "encoding/json" - - "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" -) - -// TagProps describe a tag entry in the top level tags section of a swagger spec -type TagProps struct { - Description string `json:"description,omitempty"` - Name string `json:"name,omitempty"` - ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"` -} - -// NewTag creates a new tag -func NewTag(name, description string, externalDocs *ExternalDocumentation) Tag { - return Tag{TagProps: TagProps{Description: description, Name: name, ExternalDocs: externalDocs}} -} - -// Tag allows adding meta data to a single tag that is used by the -// [Operation Object](http://goo.gl/8us55a#operationObject). -// It is not mandatory to have a Tag Object per tag used there. -// -// For more information: http://goo.gl/8us55a#tagObject -type Tag struct { - VendorExtensible - TagProps -} - -// JSONLookup implements an interface to customize json pointer lookup -func (t Tag) JSONLookup(token string) (interface{}, error) { - if ex, ok := t.Extensions[token]; ok { - return &ex, nil - } - - r, _, err := jsonpointer.GetForToken(t.TagProps, token) - return r, err -} - -// MarshalJSON marshal this to JSON -func (t Tag) MarshalJSON() ([]byte, error) { - b1, err := json.Marshal(t.TagProps) - if err != nil { - return nil, err - } - b2, err := json.Marshal(t.VendorExtensible) - if err != nil { - return nil, err - } - return swag.ConcatJSON(b1, b2), nil -} - -// UnmarshalJSON marshal this from JSON -func (t *Tag) UnmarshalJSON(data []byte) error { - if err := json.Unmarshal(data, &t.TagProps); err != nil { - return err - } - return json.Unmarshal(data, &t.VendorExtensible) -} diff --git a/vendor/github.com/go-openapi/spec/validations.go b/vendor/github.com/go-openapi/spec/validations.go deleted file mode 100644 index 6360a8ea7..000000000 --- a/vendor/github.com/go-openapi/spec/validations.go +++ /dev/null @@ -1,215 +0,0 @@ -package spec - -// CommonValidations describe common JSON-schema validations -type CommonValidations struct { - Maximum *float64 `json:"maximum,omitempty"` - ExclusiveMaximum bool `json:"exclusiveMaximum,omitempty"` - Minimum *float64 `json:"minimum,omitempty"` - ExclusiveMinimum bool `json:"exclusiveMinimum,omitempty"` - MaxLength *int64 `json:"maxLength,omitempty"` - MinLength *int64 `json:"minLength,omitempty"` - Pattern string `json:"pattern,omitempty"` - MaxItems *int64 `json:"maxItems,omitempty"` - MinItems *int64 `json:"minItems,omitempty"` - UniqueItems bool `json:"uniqueItems,omitempty"` - MultipleOf *float64 `json:"multipleOf,omitempty"` - Enum []interface{} `json:"enum,omitempty"` -} - -// SetValidations defines all validations for a simple schema. -// -// NOTE: the input is the larger set of validations available for schemas. -// For simple schemas, MinProperties and MaxProperties are ignored. -func (v *CommonValidations) SetValidations(val SchemaValidations) { - v.Maximum = val.Maximum - v.ExclusiveMaximum = val.ExclusiveMaximum - v.Minimum = val.Minimum - v.ExclusiveMinimum = val.ExclusiveMinimum - v.MaxLength = val.MaxLength - v.MinLength = val.MinLength - v.Pattern = val.Pattern - v.MaxItems = val.MaxItems - v.MinItems = val.MinItems - v.UniqueItems = val.UniqueItems - v.MultipleOf = val.MultipleOf - v.Enum = val.Enum -} - -type clearedValidation struct { - Validation string - Value interface{} -} - -type clearedValidations []clearedValidation - -func (c clearedValidations) apply(cbs []func(string, interface{})) { - for _, cb := range cbs { - for _, cleared := range c { - cb(cleared.Validation, cleared.Value) - } - } -} - -// ClearNumberValidations clears all number validations. -// -// Some callbacks may be set by the caller to capture changed values. -func (v *CommonValidations) ClearNumberValidations(cbs ...func(string, interface{})) { - done := make(clearedValidations, 0, 5) - defer func() { - done.apply(cbs) - }() - - if v.Minimum != nil { - done = append(done, clearedValidation{Validation: "minimum", Value: v.Minimum}) - v.Minimum = nil - } - if v.Maximum != nil { - done = append(done, clearedValidation{Validation: "maximum", Value: v.Maximum}) - v.Maximum = nil - } - if v.ExclusiveMaximum { - done = append(done, clearedValidation{Validation: "exclusiveMaximum", Value: v.ExclusiveMaximum}) - v.ExclusiveMaximum = false - } - if v.ExclusiveMinimum { - done = append(done, clearedValidation{Validation: "exclusiveMinimum", Value: v.ExclusiveMinimum}) - v.ExclusiveMinimum = false - } - if v.MultipleOf != nil { - done = append(done, clearedValidation{Validation: "multipleOf", Value: v.MultipleOf}) - v.MultipleOf = nil - } -} - -// ClearStringValidations clears all string validations. -// -// Some callbacks may be set by the caller to capture changed values. -func (v *CommonValidations) ClearStringValidations(cbs ...func(string, interface{})) { - done := make(clearedValidations, 0, 3) - defer func() { - done.apply(cbs) - }() - - if v.Pattern != "" { - done = append(done, clearedValidation{Validation: "pattern", Value: v.Pattern}) - v.Pattern = "" - } - if v.MinLength != nil { - done = append(done, clearedValidation{Validation: "minLength", Value: v.MinLength}) - v.MinLength = nil - } - if v.MaxLength != nil { - done = append(done, clearedValidation{Validation: "maxLength", Value: v.MaxLength}) - v.MaxLength = nil - } -} - -// ClearArrayValidations clears all array validations. -// -// Some callbacks may be set by the caller to capture changed values. -func (v *CommonValidations) ClearArrayValidations(cbs ...func(string, interface{})) { - done := make(clearedValidations, 0, 3) - defer func() { - done.apply(cbs) - }() - - if v.MaxItems != nil { - done = append(done, clearedValidation{Validation: "maxItems", Value: v.MaxItems}) - v.MaxItems = nil - } - if v.MinItems != nil { - done = append(done, clearedValidation{Validation: "minItems", Value: v.MinItems}) - v.MinItems = nil - } - if v.UniqueItems { - done = append(done, clearedValidation{Validation: "uniqueItems", Value: v.UniqueItems}) - v.UniqueItems = false - } -} - -// Validations returns a clone of the validations for a simple schema. -// -// NOTE: in the context of simple schema objects, MinProperties, MaxProperties -// and PatternProperties remain unset. -func (v CommonValidations) Validations() SchemaValidations { - return SchemaValidations{ - CommonValidations: v, - } -} - -// HasNumberValidations indicates if the validations are for numbers or integers -func (v CommonValidations) HasNumberValidations() bool { - return v.Maximum != nil || v.Minimum != nil || v.MultipleOf != nil -} - -// HasStringValidations indicates if the validations are for strings -func (v CommonValidations) HasStringValidations() bool { - return v.MaxLength != nil || v.MinLength != nil || v.Pattern != "" -} - -// HasArrayValidations indicates if the validations are for arrays -func (v CommonValidations) HasArrayValidations() bool { - return v.MaxItems != nil || v.MinItems != nil || v.UniqueItems -} - -// HasEnum indicates if the validation includes some enum constraint -func (v CommonValidations) HasEnum() bool { - return len(v.Enum) > 0 -} - -// SchemaValidations describes the validation properties of a schema -// -// NOTE: at this moment, this is not embedded in SchemaProps because this would induce a breaking change -// in the exported members: all initializers using litterals would fail. -type SchemaValidations struct { - CommonValidations - - PatternProperties SchemaProperties `json:"patternProperties,omitempty"` - MaxProperties *int64 `json:"maxProperties,omitempty"` - MinProperties *int64 `json:"minProperties,omitempty"` -} - -// HasObjectValidations indicates if the validations are for objects -func (v SchemaValidations) HasObjectValidations() bool { - return v.MaxProperties != nil || v.MinProperties != nil || v.PatternProperties != nil -} - -// SetValidations for schema validations -func (v *SchemaValidations) SetValidations(val SchemaValidations) { - v.CommonValidations.SetValidations(val) - v.PatternProperties = val.PatternProperties - v.MaxProperties = val.MaxProperties - v.MinProperties = val.MinProperties -} - -// Validations for a schema -func (v SchemaValidations) Validations() SchemaValidations { - val := v.CommonValidations.Validations() - val.PatternProperties = v.PatternProperties - val.MinProperties = v.MinProperties - val.MaxProperties = v.MaxProperties - return val -} - -// ClearObjectValidations returns a clone of the validations with all object validations cleared. -// -// Some callbacks may be set by the caller to capture changed values. -func (v *SchemaValidations) ClearObjectValidations(cbs ...func(string, interface{})) { - done := make(clearedValidations, 0, 3) - defer func() { - done.apply(cbs) - }() - - if v.MaxProperties != nil { - done = append(done, clearedValidation{Validation: "maxProperties", Value: v.MaxProperties}) - v.MaxProperties = nil - } - if v.MinProperties != nil { - done = append(done, clearedValidation{Validation: "minProperties", Value: v.MinProperties}) - v.MinProperties = nil - } - if v.PatternProperties != nil { - done = append(done, clearedValidation{Validation: "patternProperties", Value: v.PatternProperties}) - v.PatternProperties = nil - } -} diff --git a/vendor/github.com/go-openapi/spec/xml_object.go b/vendor/github.com/go-openapi/spec/xml_object.go deleted file mode 100644 index 945a46703..000000000 --- a/vendor/github.com/go-openapi/spec/xml_object.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package spec - -// XMLObject a metadata object that allows for more fine-tuned XML model definitions. -// -// For more information: http://goo.gl/8us55a#xmlObject -type XMLObject struct { - Name string `json:"name,omitempty"` - Namespace string `json:"namespace,omitempty"` - Prefix string `json:"prefix,omitempty"` - Attribute bool `json:"attribute,omitempty"` - Wrapped bool `json:"wrapped,omitempty"` -} - -// WithName sets the xml name for the object -func (x *XMLObject) WithName(name string) *XMLObject { - x.Name = name - return x -} - -// WithNamespace sets the xml namespace for the object -func (x *XMLObject) WithNamespace(namespace string) *XMLObject { - x.Namespace = namespace - return x -} - -// WithPrefix sets the xml prefix for the object -func (x *XMLObject) WithPrefix(prefix string) *XMLObject { - x.Prefix = prefix - return x -} - -// AsAttribute flags this object as xml attribute -func (x *XMLObject) AsAttribute() *XMLObject { - x.Attribute = true - return x -} - -// AsElement flags this object as an xml node -func (x *XMLObject) AsElement() *XMLObject { - x.Attribute = false - return x -} - -// AsWrapped flags this object as wrapped, this is mostly useful for array types -func (x *XMLObject) AsWrapped() *XMLObject { - x.Wrapped = true - return x -} - -// AsUnwrapped flags this object as an xml node -func (x *XMLObject) AsUnwrapped() *XMLObject { - x.Wrapped = false - return x -} diff --git a/vendor/github.com/google/cel-go/LICENSE b/vendor/github.com/google/cel-go/LICENSE index d64569567..2493ed2eb 100644 --- a/vendor/github.com/google/cel-go/LICENSE +++ b/vendor/github.com/google/cel-go/LICENSE @@ -200,3 +200,34 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + +=========================================================================== +The common/types/pb/equal.go modification of proto.Equal logic +=========================================================================== +Copyright (c) 2018 The Go 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: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of Google Inc. 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 +OWNER 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. diff --git a/vendor/github.com/google/cel-go/cel/env.go b/vendor/github.com/google/cel-go/cel/env.go index 0f97696fa..db9159c9c 100644 --- a/vendor/github.com/google/cel-go/cel/env.go +++ b/vendor/github.com/google/cel-go/cel/env.go @@ -16,6 +16,7 @@ package cel import ( "errors" + "fmt" "sync" "github.com/google/cel-go/checker" @@ -31,9 +32,7 @@ import ( ) // Source interface representing a user-provided expression. -type Source interface { - common.Source -} +type Source = common.Source // Ast representing the checked or unchecked expression, its source, and related metadata such as // source position information. @@ -52,10 +51,10 @@ func (ast *Ast) Expr() *exprpb.Expr { // IsChecked returns whether the Ast value has been successfully type-checked. func (ast *Ast) IsChecked() bool { - return ast.refMap != nil && ast.typeMap != nil + return ast.typeMap != nil && len(ast.typeMap) > 0 } -// SourceInfo returns character offset and newling position information about expression elements. +// SourceInfo returns character offset and newline position information about expression elements. func (ast *Ast) SourceInfo() *exprpb.SourceInfo { return ast.info } @@ -89,13 +88,18 @@ type Env struct { adapter ref.TypeAdapter provider ref.TypeProvider features map[int]bool - // program options tied to the environment. - progOpts []ProgramOption + + // Internal parser representation + prsr *parser.Parser // Internal checker representation - chk *checker.Env - chkErr error - once sync.Once + chk *checker.Env + chkErr error + chkOnce sync.Once + chkOpts []checker.Option + + // Program options tied to the environment + progOpts []ProgramOption } // NewEnv creates a program environment configured with the standard library of CEL functions and @@ -105,8 +109,16 @@ type Env struct { // See the EnvOption helper functions for the options that can be used to configure the // environment. func NewEnv(opts ...EnvOption) (*Env, error) { - stdOpts := append([]EnvOption{StdLib()}, opts...) - return NewCustomEnv(stdOpts...) + // Extend the statically configured standard environment, disabling eager validation to ensure + // the cost of setup for the environment is still just as cheap as it is in v0.11.x and earlier + // releases. The user provided options can easily re-enable the eager validation as they are + // processed after this default option. + stdOpts := append([]EnvOption{EagerlyValidateDeclarations(false)}, opts...) + env, err := getStdEnv() + if err != nil { + return nil, err + } + return env.Extend(stdOpts...) } // NewCustomEnv creates a custom program environment which is not automatically configured with the @@ -147,21 +159,8 @@ func (e *Env) Check(ast *Ast) (*Ast, *Issues) { pe, _ := AstToParsedExpr(ast) // Construct the internal checker env, erroring if there is an issue adding the declarations. - e.once.Do(func() { - ce := checker.NewEnv(e.Container, e.provider) - ce.EnableDynamicAggregateLiterals(true) - if e.HasFeature(FeatureDisableDynamicAggregateLiterals) { - ce.EnableDynamicAggregateLiterals(false) - } - err := ce.Add(e.declarations...) - if err != nil { - e.chkErr = err - } else { - e.chk = ce - } - }) - // The once call will ensure that this value is set or nil for all invocations. - if e.chkErr != nil { + err := e.initChecker() + if err != nil { errs := common.NewErrors(ast.Source()) errs.ReportError(common.NoLocation, e.chkErr.Error()) return nil, NewIssues(errs) @@ -201,17 +200,16 @@ func (e *Env) Compile(txt string) (*Ast, *Issues) { // issues discovered during Check. // // Note, for parse-only uses of CEL use Parse. -func (e *Env) CompileSource(src common.Source) (*Ast, *Issues) { +func (e *Env) CompileSource(src Source) (*Ast, *Issues) { ast, iss := e.ParseSource(src) if iss.Err() != nil { return nil, iss } checked, iss2 := e.Check(ast) - iss = iss.Append(iss2) - if iss.Err() != nil { - return nil, iss + if iss2.Err() != nil { + return nil, iss2 } - return checked, iss + return checked, iss2 } // Extend the current environment with additional options to produce a new Env. @@ -225,11 +223,29 @@ func (e *Env) Extend(opts ...EnvOption) (*Env, error) { if e.chkErr != nil { return nil, e.chkErr } - // Copy slices. - decsCopy := make([]*exprpb.Decl, len(e.declarations)) + + // The type-checker is configured with Declarations. The declarations may either be provided + // as options which have not yet been validated, or may come from a previous checker instance + // whose types have already been validated. + chkOptsCopy := make([]checker.Option, len(e.chkOpts)) + copy(chkOptsCopy, e.chkOpts) + + // Copy the declarations if needed. + decsCopy := []*exprpb.Decl{} + if e.chk != nil { + // If the type-checker has already been instantiated, then the e.declarations have been + // valdiated within the chk instance. + chkOptsCopy = append(chkOptsCopy, checker.ValidatedDeclarations(e.chk)) + } else { + // If the type-checker has not been instantiated, ensure the unvalidated declarations are + // provided to the extended Env instance. + decsCopy = make([]*exprpb.Decl, len(e.declarations)) + copy(decsCopy, e.declarations) + } + + // Copy macros and program options macsCopy := make([]parser.Macro, len(e.macros)) progOptsCopy := make([]ProgramOption, len(e.progOpts)) - copy(decsCopy, e.declarations) copy(macsCopy, e.macros) copy(progOptsCopy, e.progOpts) @@ -273,6 +289,7 @@ func (e *Env) Extend(opts ...EnvOption) (*Env, error) { adapter: adapter, features: featuresCopy, provider: provider, + chkOpts: chkOptsCopy, } return ext.configure(opts) } @@ -280,13 +297,13 @@ func (e *Env) Extend(opts ...EnvOption) (*Env, error) { // HasFeature checks whether the environment enables the given feature // flag, as enumerated in options.go. func (e *Env) HasFeature(flag int) bool { - _, has := e.features[flag] - return has + enabled, has := e.features[flag] + return has && enabled } // Parse parses the input expression value `txt` to a Ast and/or a set of Issues. // -// This form of Parse creates a common.Source value for the input `txt` and forwards to the +// This form of Parse creates a Source value for the input `txt` and forwards to the // ParseSource method. func (e *Env) Parse(txt string) (*Ast, *Issues) { src := common.NewTextSource(txt) @@ -300,15 +317,15 @@ func (e *Env) Parse(txt string) (*Ast, *Issues) { // // It is possible to have both non-nil Ast and Issues values returned from this call; however, // the mere presence of an Ast does not imply that it is valid for use. -func (e *Env) ParseSource(src common.Source) (*Ast, *Issues) { - res, errs := parser.ParseWithMacros(src, e.macros) +func (e *Env) ParseSource(src Source) (*Ast, *Issues) { + res, errs := e.prsr.Parse(src) if len(errs.GetErrors()) > 0 { return nil, &Issues{errs: errs} } // Manually create the Ast to ensure that the text source information is propagated on // subsequent calls to Check. return &Ast{ - source: Source(src), + source: src, expr: res.GetExpr(), info: res.GetSourceInfo()}, nil } @@ -325,11 +342,6 @@ func (e *Env) Program(ast *Ast, opts ...ProgramOption) (Program, error) { return newProgram(e, ast, optSet) } -// SetFeature sets the given feature flag, as enumerated in options.go. -func (e *Env) SetFeature(flag int) { - e.features[flag] = true -} - // TypeAdapter returns the `ref.TypeAdapter` configured for the environment. func (e *Env) TypeAdapter() ref.TypeAdapter { return e.adapter @@ -402,6 +414,16 @@ func (e *Env) ResidualAst(a *Ast, details *EvalDetails) (*Ast, error) { return checked, nil } +// EstimateCost estimates the cost of a type checked CEL expression using the length estimates of input data and +// extension functions provided by estimator. +func (e *Env) EstimateCost(ast *Ast, estimator checker.CostEstimator) (checker.CostEstimate, error) { + checked, err := AstToCheckedExpr(ast) + if err != nil { + return checker.CostEstimate{}, fmt.Errorf("EsimateCost could not inspect Ast: %v", err) + } + return checker.Cost(checked, estimator), nil +} + // configure applies a series of EnvOptions to the current environment. func (e *Env) configure(opts []EnvOption) (*Env, error) { // Customized the environment using the provided EnvOption values. If an error is @@ -413,9 +435,54 @@ func (e *Env) configure(opts []EnvOption) (*Env, error) { return nil, err } } + + // Configure the parser. + prsrOpts := []parser.Option{parser.Macros(e.macros...)} + if e.HasFeature(featureEnableMacroCallTracking) { + prsrOpts = append(prsrOpts, parser.PopulateMacroCalls(true)) + } + e.prsr, err = parser.NewParser(prsrOpts...) + if err != nil { + return nil, err + } + + // The simplest way to eagerly validate declarations on environment creation is to compile + // a dummy program and check for the presence of e.chkErr being non-nil. + if e.HasFeature(featureEagerlyValidateDeclarations) { + err := e.initChecker() + if err != nil { + return nil, err + } + } + return e, nil } +func (e *Env) initChecker() error { + e.chkOnce.Do(func() { + chkOpts := []checker.Option{} + chkOpts = append(chkOpts, e.chkOpts...) + chkOpts = append(chkOpts, + checker.HomogeneousAggregateLiterals( + e.HasFeature(featureDisableDynamicAggregateLiterals)), + checker.CrossTypeNumericComparisons( + e.HasFeature(featureCrossTypeNumericComparisons))) + + ce, err := checker.NewEnv(e.Container, e.provider, chkOpts...) + if err != nil { + e.chkErr = err + return + } + err = ce.Add(e.declarations...) + if err != nil { + e.chkErr = err + return + } + e.chk = ce + }) + return e.chkErr +} + // Issues defines methods for inspecting the error details of parse and check calls. // // Note: in the future, non-fatal warnings and notices may be inspectable via the Issues struct. @@ -454,6 +521,9 @@ func (i *Issues) Append(other *Issues) *Issues { if i == nil { return other } + if other == nil { + return i + } return NewIssues(i.errs.Append(other.errs.GetErrors())) } @@ -464,3 +534,17 @@ func (i *Issues) String() string { } return i.errs.ToDisplayString() } + +// getStdEnv lazy initializes the CEL standard environment. +func getStdEnv() (*Env, error) { + stdEnvInit.Do(func() { + stdEnv, stdEnvErr = NewCustomEnv(StdLib(), EagerlyValidateDeclarations(true)) + }) + return stdEnv, stdEnvErr +} + +var ( + stdEnvInit sync.Once + stdEnv *Env + stdEnvErr error +) diff --git a/vendor/github.com/google/cel-go/cel/io.go b/vendor/github.com/google/cel-go/cel/io.go index b6cf58d92..02b702444 100644 --- a/vendor/github.com/google/cel-go/cel/io.go +++ b/vendor/github.com/google/cel-go/cel/io.go @@ -15,16 +15,36 @@ package cel import ( + "errors" "fmt" + "reflect" "github.com/google/cel-go/common" + "github.com/google/cel-go/common/types" + "github.com/google/cel-go/common/types/ref" + "github.com/google/cel-go/common/types/traits" "github.com/google/cel-go/parser" + "google.golang.org/protobuf/proto" + exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" + anypb "google.golang.org/protobuf/types/known/anypb" ) // CheckedExprToAst converts a checked expression proto message to an Ast. func CheckedExprToAst(checkedExpr *exprpb.CheckedExpr) *Ast { + return CheckedExprToAstWithSource(checkedExpr, nil) +} + +// CheckedExprToAstWithSource converts a checked expression proto message to an Ast, +// using the provided Source as the textual contents. +// +// In general the source is not necessary unless the AST has been modified between the +// `Parse` and `Check` calls as an `Ast` created from the `Parse` step will carry the source +// through future calls. +// +// Prefer CheckedExprToAst if loading expressions from storage. +func CheckedExprToAstWithSource(checkedExpr *exprpb.CheckedExpr, src Source) *Ast { refMap := checkedExpr.GetReferenceMap() if refMap == nil { refMap = map[int64]*exprpb.Reference{} @@ -33,10 +53,17 @@ func CheckedExprToAst(checkedExpr *exprpb.CheckedExpr) *Ast { if typeMap == nil { typeMap = map[int64]*exprpb.Type{} } + si := checkedExpr.GetSourceInfo() + if si == nil { + si = &exprpb.SourceInfo{} + } + if src == nil { + src = common.NewInfoSource(si) + } return &Ast{ expr: checkedExpr.GetExpr(), - info: checkedExpr.GetSourceInfo(), - source: common.NewInfoSource(checkedExpr.GetSourceInfo()), + info: si, + source: src, refMap: refMap, typeMap: typeMap, } @@ -59,14 +86,28 @@ func AstToCheckedExpr(a *Ast) (*exprpb.CheckedExpr, error) { // ParsedExprToAst converts a parsed expression proto message to an Ast. func ParsedExprToAst(parsedExpr *exprpb.ParsedExpr) *Ast { + return ParsedExprToAstWithSource(parsedExpr, nil) +} + +// ParsedExprToAstWithSource converts a parsed expression proto message to an Ast, +// using the provided Source as the textual contents. +// +// In general you only need this if you need to recheck a previously checked +// expression, or if you need to separately check a subset of an expression. +// +// Prefer ParsedExprToAst if loading expressions from storage. +func ParsedExprToAstWithSource(parsedExpr *exprpb.ParsedExpr, src Source) *Ast { si := parsedExpr.GetSourceInfo() if si == nil { si = &exprpb.SourceInfo{} } + if src == nil { + src = common.NewInfoSource(si) + } return &Ast{ expr: parsedExpr.GetExpr(), info: si, - source: common.NewInfoSource(si), + source: src, } } @@ -87,3 +128,153 @@ func AstToString(a *Ast) (string, error) { info := a.SourceInfo() return parser.Unparse(expr, info) } + +// RefValueToValue converts between ref.Val and api.expr.Value. +// The result Value is the serialized proto form. The ref.Val must not be error or unknown. +func RefValueToValue(res ref.Val) (*exprpb.Value, error) { + switch res.Type() { + case types.BoolType: + return &exprpb.Value{ + Kind: &exprpb.Value_BoolValue{BoolValue: res.Value().(bool)}}, nil + case types.BytesType: + return &exprpb.Value{ + Kind: &exprpb.Value_BytesValue{BytesValue: res.Value().([]byte)}}, nil + case types.DoubleType: + return &exprpb.Value{ + Kind: &exprpb.Value_DoubleValue{DoubleValue: res.Value().(float64)}}, nil + case types.IntType: + return &exprpb.Value{ + Kind: &exprpb.Value_Int64Value{Int64Value: res.Value().(int64)}}, nil + case types.ListType: + l := res.(traits.Lister) + sz := l.Size().(types.Int) + elts := make([]*exprpb.Value, 0, int64(sz)) + for i := types.Int(0); i < sz; i++ { + v, err := RefValueToValue(l.Get(i)) + if err != nil { + return nil, err + } + elts = append(elts, v) + } + return &exprpb.Value{ + Kind: &exprpb.Value_ListValue{ + ListValue: &exprpb.ListValue{Values: elts}}}, nil + case types.MapType: + mapper := res.(traits.Mapper) + sz := mapper.Size().(types.Int) + entries := make([]*exprpb.MapValue_Entry, 0, int64(sz)) + for it := mapper.Iterator(); it.HasNext().(types.Bool); { + k := it.Next() + v := mapper.Get(k) + kv, err := RefValueToValue(k) + if err != nil { + return nil, err + } + vv, err := RefValueToValue(v) + if err != nil { + return nil, err + } + entries = append(entries, &exprpb.MapValue_Entry{Key: kv, Value: vv}) + } + return &exprpb.Value{ + Kind: &exprpb.Value_MapValue{ + MapValue: &exprpb.MapValue{Entries: entries}}}, nil + case types.NullType: + return &exprpb.Value{ + Kind: &exprpb.Value_NullValue{}}, nil + case types.StringType: + return &exprpb.Value{ + Kind: &exprpb.Value_StringValue{StringValue: res.Value().(string)}}, nil + case types.TypeType: + typeName := res.(ref.Type).TypeName() + return &exprpb.Value{Kind: &exprpb.Value_TypeValue{TypeValue: typeName}}, nil + case types.UintType: + return &exprpb.Value{ + Kind: &exprpb.Value_Uint64Value{Uint64Value: res.Value().(uint64)}}, nil + default: + any, err := res.ConvertToNative(anyPbType) + if err != nil { + return nil, err + } + return &exprpb.Value{ + Kind: &exprpb.Value_ObjectValue{ObjectValue: any.(*anypb.Any)}}, nil + } +} + +var ( + typeNameToTypeValue = map[string]*types.TypeValue{ + "bool": types.BoolType, + "bytes": types.BytesType, + "double": types.DoubleType, + "null_type": types.NullType, + "int": types.IntType, + "list": types.ListType, + "map": types.MapType, + "string": types.StringType, + "type": types.TypeType, + "uint": types.UintType, + } + + anyPbType = reflect.TypeOf(&anypb.Any{}) +) + +// ValueToRefValue converts between exprpb.Value and ref.Val. +func ValueToRefValue(adapter ref.TypeAdapter, v *exprpb.Value) (ref.Val, error) { + switch v.Kind.(type) { + case *exprpb.Value_NullValue: + return types.NullValue, nil + case *exprpb.Value_BoolValue: + return types.Bool(v.GetBoolValue()), nil + case *exprpb.Value_Int64Value: + return types.Int(v.GetInt64Value()), nil + case *exprpb.Value_Uint64Value: + return types.Uint(v.GetUint64Value()), nil + case *exprpb.Value_DoubleValue: + return types.Double(v.GetDoubleValue()), nil + case *exprpb.Value_StringValue: + return types.String(v.GetStringValue()), nil + case *exprpb.Value_BytesValue: + return types.Bytes(v.GetBytesValue()), nil + case *exprpb.Value_ObjectValue: + any := v.GetObjectValue() + msg, err := anypb.UnmarshalNew(any, proto.UnmarshalOptions{DiscardUnknown: true}) + if err != nil { + return nil, err + } + return adapter.NativeToValue(msg.(proto.Message)), nil + case *exprpb.Value_MapValue: + m := v.GetMapValue() + entries := make(map[ref.Val]ref.Val) + for _, entry := range m.Entries { + key, err := ValueToRefValue(adapter, entry.Key) + if err != nil { + return nil, err + } + pb, err := ValueToRefValue(adapter, entry.Value) + if err != nil { + return nil, err + } + entries[key] = pb + } + return adapter.NativeToValue(entries), nil + case *exprpb.Value_ListValue: + l := v.GetListValue() + elts := make([]ref.Val, len(l.Values)) + for i, e := range l.Values { + rv, err := ValueToRefValue(adapter, e) + if err != nil { + return nil, err + } + elts[i] = rv + } + return adapter.NativeToValue(elts), nil + case *exprpb.Value_TypeValue: + typeName := v.GetTypeValue() + tv, ok := typeNameToTypeValue[typeName] + if ok { + return tv, nil + } + return types.NewObjectTypeValue(typeName), nil + } + return nil, errors.New("unknown value") +} diff --git a/vendor/github.com/google/cel-go/cel/library.go b/vendor/github.com/google/cel-go/cel/library.go index cef161d6a..5d63bca8b 100644 --- a/vendor/github.com/google/cel-go/cel/library.go +++ b/vendor/github.com/google/cel-go/cel/library.go @@ -20,14 +20,14 @@ import ( "github.com/google/cel-go/parser" ) -// Library provides a collection of EnvOption and ProgramOption values used to confiugre a CEL +// Library provides a collection of EnvOption and ProgramOption values used to configure a CEL // environment for a particular use case or with a related set of functionality. // // Note, the ProgramOption values provided by a library are expected to be static and not vary // between calls to Env.Program(). If there is a need for such dynamic configuration, prefer to // configure these options outside the Library and within the Env.Program() call directly. type Library interface { - // CompileOptions returns a collection of funcitional options for configuring the Parse / Check + // CompileOptions returns a collection of functional options for configuring the Parse / Check // environment. CompileOptions() []EnvOption diff --git a/vendor/github.com/google/cel-go/cel/options.go b/vendor/github.com/google/cel-go/cel/options.go index 1da6ecd79..87de33af3 100644 --- a/vendor/github.com/google/cel-go/cel/options.go +++ b/vendor/github.com/google/cel-go/cel/options.go @@ -17,6 +17,13 @@ package cel import ( "fmt" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protodesc" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/reflect/protoregistry" + "google.golang.org/protobuf/types/dynamicpb" + + "github.com/google/cel-go/checker/decls" "github.com/google/cel-go/common/containers" "github.com/google/cel-go/common/types/pb" "github.com/google/cel-go/common/types/ref" @@ -24,11 +31,6 @@ import ( "github.com/google/cel-go/interpreter/functions" "github.com/google/cel-go/parser" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/reflect/protodesc" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/reflect/protoregistry" - exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" descpb "google.golang.org/protobuf/types/descriptorpb" ) @@ -44,7 +46,17 @@ const ( // provided as variables to the expression, as well as via conversion // of well-known dynamic types, or with unchecked expressions. // Affects checking. Provides a subset of standard behavior. - FeatureDisableDynamicAggregateLiterals + featureDisableDynamicAggregateLiterals + + // Enable the tracking of function call expressions replaced by macros. + featureEnableMacroCallTracking + + // Enable the use of cross-type numeric comparisons at the type-checker. + featureCrossTypeNumericComparisons + + // Enable eager validation of declarations to ensure that Env values created + // with `Extend` inherit a validated list of declarations from the parent Env. + featureEagerlyValidateDeclarations ) // EnvOption is a functional interface for configuring the environment. @@ -95,14 +107,16 @@ func Declarations(decls ...*exprpb.Decl) EnvOption { } } -// Features sets the given feature flags. See list of Feature constants above. -func Features(flags ...int) EnvOption { - return func(e *Env) (*Env, error) { - for _, flag := range flags { - e.SetFeature(flag) - } - return e, nil - } +// EagerlyValidateDeclarations ensures that any collisions between configured declarations are caught +// at the time of the `NewEnv` call. +// +// Eagerly validating declarations is also useful for bootstrapping a base `cel.Env` value. +// Calls to base `Env.Extend()` will be significantly faster when declarations are eagerly validated +// as declarations will be collision-checked at most once and only incrementally by way of `Extend` +// +// Disabled by default as not all environments are used for type-checking. +func EagerlyValidateDeclarations(enabled bool) EnvOption { + return features(featureEagerlyValidateDeclarations, enabled) } // HomogeneousAggregateLiterals option ensures that list and map literal entry types must agree @@ -112,7 +126,7 @@ func Features(flags ...int) EnvOption { // expression, as well as via conversion of well-known dynamic types, or with unchecked // expressions. func HomogeneousAggregateLiterals() EnvOption { - return Features(FeatureDisableDynamicAggregateLiterals) + return features(featureDisableDynamicAggregateLiterals, true) } // Macros option extends the macro set configured in the environment. @@ -333,8 +347,7 @@ func Functions(funcs ...*functions.Overload) ProgramOption { // The vars value may either be an `interpreter.Activation` instance or a `map[string]interface{}`. func Globals(vars interface{}) ProgramOption { return func(p *prog) (*prog, error) { - defaultVars, err := - interpreter.NewActivation(vars) + defaultVars, err := interpreter.NewActivation(vars) if err != nil { return nil, err } @@ -343,6 +356,16 @@ func Globals(vars interface{}) ProgramOption { } } +// OptimizeRegex provides a way to replace the InterpretableCall for regex functions. This can be used +// to compile regex string constants at program creation time and report any errors and then use the +// compiled regex for all regex function invocations. +func OptimizeRegex(regexOptimizations ...*interpreter.RegexOptimization) ProgramOption { + return func(p *prog) (*prog, error) { + p.regexOptimizations = append(p.regexOptimizations, regexOptimizations...) + return p, nil + } +} + // EvalOption indicates an evaluation option that may affect the evaluation behavior or information // in the output result. type EvalOption int @@ -355,7 +378,9 @@ const ( OptExhaustiveEval EvalOption = 1< 0 { + decorators = append(decorators, interpreter.InterruptableEval()) + } // Enable constant folding first. if p.evalOpts&OptOptimize == OptOptimize { decorators = append(decorators, interpreter.Optimize()) + p.regexOptimizations = append(p.regexOptimizations, interpreter.MatchesRegexOptimization) } - // Enable exhaustive eval over state tracking since it offers a superset of features. - if p.evalOpts&OptExhaustiveEval == OptExhaustiveEval { - // State tracking requires that each Eval() call operate on an isolated EvalState - // object; hence, the presence of the factory. - factory := func(state interpreter.EvalState) (Program, error) { - decs := append(decorators, interpreter.ExhaustiveEval(state)) - clone := &prog{ - evalOpts: p.evalOpts, - defaultVars: p.defaultVars, - Env: e, - dispatcher: disp, - interpreter: interp} - return initInterpretable(clone, ast, decs) + // Enable regex compilation of constants immediately after folding constants. + if len(p.regexOptimizations) > 0 { + decorators = append(decorators, interpreter.CompileRegexConstants(p.regexOptimizations...)) + } + + // Enable exhaustive eval, state tracking and cost tracking last since they require a factory. + if p.evalOpts&(OptExhaustiveEval|OptTrackState|OptTrackCost) != 0 { + factory := func(state interpreter.EvalState, costTracker *interpreter.CostTracker) (Program, error) { + costTracker.Estimator = p.callCostEstimator + costTracker.Limit = p.costLimit + decs := decorators + var observers []interpreter.EvalObserver + + if p.evalOpts&(OptExhaustiveEval|OptTrackState) != 0 { + // EvalStateObserver is required for OptExhaustiveEval. + observers = append(observers, interpreter.EvalStateObserver(state)) + } + if p.evalOpts&OptTrackCost == OptTrackCost { + observers = append(observers, interpreter.CostObserver(costTracker)) + } + + // Enable exhaustive eval over a basic observer since it offers a superset of features. + if p.evalOpts&OptExhaustiveEval == OptExhaustiveEval { + decs = append(decs, interpreter.ExhaustiveEval(), interpreter.Observe(observers...)) + } else if len(observers) > 0 { + decs = append(decs, interpreter.Observe(observers...)) + } + + return p.clone().initInterpretable(ast, decs) } - return initProgGen(factory) + return newProgGen(factory) } - // Enable state tracking last since it too requires the factory approach but is less - // featured than the ExhaustiveEval decorator. - if p.evalOpts&OptTrackState == OptTrackState { - factory := func(state interpreter.EvalState) (Program, error) { - decs := append(decorators, interpreter.TrackState(state)) - clone := &prog{ - evalOpts: p.evalOpts, - defaultVars: p.defaultVars, - Env: e, - dispatcher: disp, - interpreter: interp} - return initInterpretable(clone, ast, decs) - } - return initProgGen(factory) - } - return initInterpretable(p, ast, decorators) + return p.initInterpretable(ast, decorators) } -// initProgGen tests the factory object by calling it once and returns a factory-based Program if -// the test is successful. -func initProgGen(factory progFactory) (Program, error) { - // Test the factory to make sure that configuration errors are spotted at config - _, err := factory(interpreter.NewEvalState()) - if err != nil { - return nil, err - } - return &progGen{factory: factory}, nil -} - -// initIterpretable creates a checked or unchecked interpretable depending on whether the Ast -// has been run through the type-checker. -func initInterpretable( - p *prog, - ast *Ast, - decorators []interpreter.InterpretableDecorator) (Program, error) { - var err error - // Unchecked programs do not contain type and reference information and may be - // slower to execute than their checked counterparts. +func (p *prog) initInterpretable(ast *Ast, decs []interpreter.InterpretableDecorator) (*prog, error) { + // Unchecked programs do not contain type and reference information and may be slower to execute. if !ast.IsChecked() { - p.interpretable, err = - p.interpreter.NewUncheckedInterpretable(ast.Expr(), decorators...) + interpretable, err := + p.interpreter.NewUncheckedInterpretable(ast.Expr(), decs...) if err != nil { return nil, err } + p.interpretable = interpretable return p, nil } - // When the AST has been checked it contains metadata that can be used to speed up program - // execution. - var checked *exprpb.CheckedExpr - checked, err = AstToCheckedExpr(ast) - if err != nil { - return nil, err - } - p.interpretable, err = p.interpreter.NewInterpretable(checked, decorators...) - if err != nil { - return nil, err - } + // When the AST has been checked it contains metadata that can be used to speed up program execution. + var checked *exprpb.CheckedExpr + checked, err := AstToCheckedExpr(ast) + if err != nil { + return nil, err + } + interpretable, err := p.interpreter.NewInterpretable(checked, decs...) + if err != nil { + return nil, err + } + p.interpretable = interpretable return p, nil } @@ -240,13 +259,24 @@ func (p *prog) Eval(input interface{}) (v ref.Val, det *EvalDetails, err error) // function. defer func() { if r := recover(); r != nil { - err = fmt.Errorf("internal error: %v", r) + switch t := r.(type) { + case interpreter.EvalCancelledError: + err = t + default: + err = fmt.Errorf("internal error: %v", r) + } } }() // Build a hierarchical activation if there are default vars set. - vars, err := interpreter.NewActivation(input) - if err != nil { - return + var vars interpreter.Activation + switch v := input.(type) { + case interpreter.Activation: + vars = v + case map[string]interface{}: + vars = activationPool.Setup(v) + defer activationPool.Put(vars) + default: + return nil, nil, fmt.Errorf("invalid input, wanted Activation or map[string]interface{}, got: (%T)%v", input, input) } if p.defaultVars != nil { vars = interpreter.NewHierarchicalActivation(p.defaultVars, vars) @@ -261,23 +291,66 @@ func (p *prog) Eval(input interface{}) (v ref.Val, det *EvalDetails, err error) return } +// ContextEval implements the Program interface. +func (p *prog) ContextEval(ctx context.Context, input interface{}) (ref.Val, *EvalDetails, error) { + if ctx == nil { + return nil, nil, fmt.Errorf("context can not be nil") + } + // Configure the input, making sure to wrap Activation inputs in the special ctxActivation which + // exposes the #interrupted variable and manages rate-limited checks of the ctx.Done() state. + var vars interpreter.Activation + switch v := input.(type) { + case interpreter.Activation: + vars = ctxActivationPool.Setup(v, ctx.Done(), p.interruptCheckFrequency) + defer ctxActivationPool.Put(vars) + case map[string]interface{}: + rawVars := activationPool.Setup(v) + defer activationPool.Put(rawVars) + vars = ctxActivationPool.Setup(rawVars, ctx.Done(), p.interruptCheckFrequency) + defer ctxActivationPool.Put(vars) + default: + return nil, nil, fmt.Errorf("invalid input, wanted Activation or map[string]interface{}, got: (%T)%v", input, input) + } + return p.Eval(vars) +} + // Cost implements the Coster interface method. func (p *prog) Cost() (min, max int64) { return estimateCost(p.interpretable) } +// progFactory is a helper alias for marking a program creation factory function. +type progFactory func(interpreter.EvalState, *interpreter.CostTracker) (Program, error) + +// progGen holds a reference to a progFactory instance and implements the Program interface. +type progGen struct { + factory progFactory +} + +// newProgGen tests the factory object by calling it once and returns a factory-based Program if +// the test is successful. +func newProgGen(factory progFactory) (Program, error) { + // Test the factory to make sure that configuration errors are spotted at config + _, err := factory(interpreter.NewEvalState(), &interpreter.CostTracker{}) + if err != nil { + return nil, err + } + return &progGen{factory: factory}, nil +} + // Eval implements the Program interface method. func (gen *progGen) Eval(input interface{}) (ref.Val, *EvalDetails, error) { // The factory based Eval() differs from the standard evaluation model in that it generates a // new EvalState instance for each call to ensure that unique evaluations yield unique stateful // results. state := interpreter.NewEvalState() - det := &EvalDetails{state: state} + costTracker := &interpreter.CostTracker{} + det := &EvalDetails{state: state, costTracker: costTracker} // Generate a new instance of the interpretable using the factory configured during the call to // newProgram(). It is incredibly unlikely that the factory call will generate an error given // the factory test performed within the Program() call. - p, err := gen.factory(state) + p, err := gen.factory(state, costTracker) if err != nil { return nil, det, err } @@ -290,20 +363,44 @@ func (gen *progGen) Eval(input interface{}) (ref.Val, *EvalDetails, error) { return v, det, nil } +// ContextEval implements the Program interface method. +func (gen *progGen) ContextEval(ctx context.Context, input interface{}) (ref.Val, *EvalDetails, error) { + if ctx == nil { + return nil, nil, fmt.Errorf("context can not be nil") + } + // The factory based Eval() differs from the standard evaluation model in that it generates a + // new EvalState instance for each call to ensure that unique evaluations yield unique stateful + // results. + state := interpreter.NewEvalState() + costTracker := &interpreter.CostTracker{} + det := &EvalDetails{state: state, costTracker: costTracker} + + // Generate a new instance of the interpretable using the factory configured during the call to + // newProgram(). It is incredibly unlikely that the factory call will generate an error given + // the factory test performed within the Program() call. + p, err := gen.factory(state, costTracker) + if err != nil { + return nil, det, err + } + + // Evaluate the input, returning the result and the 'state' within EvalDetails. + v, _, err := p.ContextEval(ctx, input) + if err != nil { + return v, det, err + } + return v, det, nil +} + // Cost implements the Coster interface method. func (gen *progGen) Cost() (min, max int64) { // Use an empty state value since no evaluation is performed. - p, err := gen.factory(emptyEvalState) + p, err := gen.factory(emptyEvalState, nil) if err != nil { return 0, math.MaxInt64 } return estimateCost(p) } -var ( - emptyEvalState = interpreter.NewEvalState() -) - // EstimateCost returns the heuristic cost interval for the program. func EstimateCost(p Program) (min, max int64) { return estimateCost(p) @@ -316,3 +413,140 @@ func estimateCost(i interface{}) (min, max int64) { } return c.Cost() } + +type ctxEvalActivation struct { + parent interpreter.Activation + interrupt <-chan struct{} + interruptCheckCount uint + interruptCheckFrequency uint +} + +// ResolveName implements the Activation interface method, but adds a special #interrupted variable +// which is capable of testing whether a 'done' signal is provided from a context.Context channel. +func (a *ctxEvalActivation) ResolveName(name string) (interface{}, bool) { + if name == "#interrupted" { + a.interruptCheckCount++ + if a.interruptCheckCount%a.interruptCheckFrequency == 0 { + select { + case <-a.interrupt: + return true, true + default: + return nil, false + } + } + return nil, false + } + return a.parent.ResolveName(name) +} + +func (a *ctxEvalActivation) Parent() interpreter.Activation { + return a.parent +} + +func newCtxEvalActivationPool() *ctxEvalActivationPool { + return &ctxEvalActivationPool{ + Pool: sync.Pool{ + New: func() interface{} { + return &ctxEvalActivation{} + }, + }, + } +} + +type ctxEvalActivationPool struct { + sync.Pool +} + +// Setup initializes a pooled Activation with the ability check for context.Context cancellation +func (p *ctxEvalActivationPool) Setup(vars interpreter.Activation, done <-chan struct{}, interruptCheckRate uint) *ctxEvalActivation { + a := p.Pool.Get().(*ctxEvalActivation) + a.parent = vars + a.interrupt = done + a.interruptCheckCount = 0 + a.interruptCheckFrequency = interruptCheckRate + return a +} + +type evalActivation struct { + vars map[string]interface{} + lazyVars map[string]interface{} +} + +// ResolveName looks up the value of the input variable name, if found. +// +// Lazy bindings may be supplied within the map-based input in either of the following forms: +// - func() interface{} +// - func() ref.Val +// +// The lazy binding will only be invoked once per evaluation. +// +// Values which are not represented as ref.Val types on input may be adapted to a ref.Val using +// the ref.TypeAdapter configured in the environment. +func (a *evalActivation) ResolveName(name string) (interface{}, bool) { + v, found := a.vars[name] + if !found { + return nil, false + } + switch obj := v.(type) { + case func() ref.Val: + if resolved, found := a.lazyVars[name]; found { + return resolved, true + } + lazy := obj() + a.lazyVars[name] = lazy + return lazy, true + case func() interface{}: + if resolved, found := a.lazyVars[name]; found { + return resolved, true + } + lazy := obj() + a.lazyVars[name] = lazy + return lazy, true + default: + return obj, true + } +} + +// Parent implements the interpreter.Activation interface +func (a *evalActivation) Parent() interpreter.Activation { + return nil +} + +func newEvalActivationPool() *evalActivationPool { + return &evalActivationPool{ + Pool: sync.Pool{ + New: func() interface{} { + return &evalActivation{lazyVars: make(map[string]interface{})} + }, + }, + } +} + +type evalActivationPool struct { + sync.Pool +} + +// Setup initializes a pooled Activation object with the map input. +func (p *evalActivationPool) Setup(vars map[string]interface{}) *evalActivation { + a := p.Pool.Get().(*evalActivation) + a.vars = vars + return a +} + +func (p *evalActivationPool) Put(value interface{}) { + a := value.(*evalActivation) + for k := range a.lazyVars { + delete(a.lazyVars, k) + } + p.Pool.Put(a) +} + +var ( + emptyEvalState = interpreter.NewEvalState() + + // activationPool is an internally managed pool of Activation values that wrap map[string]interface{} inputs + activationPool = newEvalActivationPool() + + // ctxActivationPool is an internally managed pool of Activation values that expose a special #interrupted variable + ctxActivationPool = newCtxEvalActivationPool() +) diff --git a/vendor/github.com/google/cel-go/checker/checker.go b/vendor/github.com/google/cel-go/checker/checker.go index 2394d2dcd..4e7929d12 100644 --- a/vendor/github.com/google/cel-go/checker/checker.go +++ b/vendor/github.com/google/cel-go/checker/checker.go @@ -112,7 +112,8 @@ func (c *checker) check(e *exprpb.Expr) { case *exprpb.Expr_ComprehensionExpr: c.checkComprehension(e) default: - panic(fmt.Sprintf("Unrecognized ast type: %v", reflect.TypeOf(e))) + c.errors.ReportError( + c.location(e), "Unrecognized ast type: %v", reflect.TypeOf(e)) } } @@ -167,11 +168,9 @@ func (c *checker) checkSelect(e *exprpb.Expr) { if found { ident := c.env.LookupIdent(qname) if ident != nil { - if sel.TestOnly { - c.errors.expressionDoesNotSelectField(c.location(e)) - c.setType(e, decls.Bool) - return - } + // We don't check for a TestOnly expression here since the `found` result is + // always going to be false for TestOnly expressions. + // Rewrite the node to be a variable reference to the resolved fully-qualified // variable name. c.setType(e, ident.GetIdent().Type) @@ -207,7 +206,7 @@ func (c *checker) checkSelect(e *exprpb.Expr) { resultType = fieldType.Type } case kindTypeParam: - // Set the operand type to DYN to prevent assignment to a potentionally incorrect type + // Set the operand type to DYN to prevent assignment to a potentially incorrect type // at a later point in type-checking. The isAssignable call will update the type // substitutions for the type param under the covers. c.isAssignable(decls.Dyn, targetType) @@ -322,6 +321,12 @@ func (c *checker) resolveOverload( var resultType *exprpb.Type var checkedRef *exprpb.Reference for _, overload := range fn.GetFunction().Overloads { + // Determine whether the overload is currently considered. + if c.env.isOverloadDisabled(overload.GetOverloadId()) { + continue + } + + // Ensure the call style for the overload matches. if (target == nil && overload.IsInstanceFunction) || (target != nil && !overload.IsInstanceFunction) { // not a compatible call style. @@ -329,26 +334,26 @@ func (c *checker) resolveOverload( } overloadType := decls.NewFunctionType(overload.ResultType, overload.Params...) - if len(overload.TypeParams) > 0 { + if len(overload.GetTypeParams()) > 0 { // Instantiate overload's type with fresh type variables. substitutions := newMapping() - for _, typePar := range overload.TypeParams { + for _, typePar := range overload.GetTypeParams() { substitutions.add(decls.NewTypeParamType(typePar), c.newTypeVar()) } overloadType = substitute(substitutions, overloadType, false) } - candidateArgTypes := overloadType.GetFunction().ArgTypes + candidateArgTypes := overloadType.GetFunction().GetArgTypes() if c.isAssignableList(argTypes, candidateArgTypes) { if checkedRef == nil { - checkedRef = newFunctionReference(overload.OverloadId) + checkedRef = newFunctionReference(overload.GetOverloadId()) } else { - checkedRef.OverloadId = append(checkedRef.OverloadId, overload.OverloadId) + checkedRef.OverloadId = append(checkedRef.OverloadId, overload.GetOverloadId()) } // First matching overload, determines result type. fnResultType := substitute(c.mappings, - overloadType.GetFunction().ResultType, + overloadType.GetFunction().GetResultType(), false) if resultType == nil { resultType = fnResultType @@ -477,7 +482,7 @@ func (c *checker) checkComprehension(e *exprpb.Expr) { // Ranges over the keys. varType = rangeType.GetMapType().KeyType case kindDyn, kindError, kindTypeParam: - // Set the range type to DYN to prevent assignment to a potentionally incorrect type + // Set the range type to DYN to prevent assignment to a potentially incorrect type // at a later point in type-checking. The isAssignable call will update the type // substitutions for the type param under the covers. c.isAssignable(decls.Dyn, rangeType) @@ -572,7 +577,9 @@ func (c *checker) lookupFieldType(l common.Location, messageType string, fieldNa func (c *checker) setType(e *exprpb.Expr, t *exprpb.Type) { if old, found := c.types[e.Id]; found && !proto.Equal(old, t) { - panic(fmt.Sprintf("(Incompatible) Type already exists for expression: %v(%d) old:%v, new:%v", e, e.Id, old, t)) + c.errors.ReportError(c.location(e), + "(Incompatible) Type already exists for expression: %v(%d) old:%v, new:%v", e, e.GetId(), old, t) + return } c.types[e.Id] = t } @@ -583,7 +590,9 @@ func (c *checker) getType(e *exprpb.Expr) *exprpb.Type { func (c *checker) setReference(e *exprpb.Expr, r *exprpb.Reference) { if old, found := c.references[e.Id]; found && !proto.Equal(old, r) { - panic(fmt.Sprintf("Reference already exists for expression: %v(%d) old:%v, new:%v", e, e.Id, old, r)) + c.errors.ReportError(c.location(e), + "Reference already exists for expression: %v(%d) old:%v, new:%v", e, e.Id, old, r) + return } c.references[e.Id] = r } diff --git a/vendor/github.com/google/cel-go/checker/cost.go b/vendor/github.com/google/cel-go/checker/cost.go new file mode 100644 index 000000000..75142ebc1 --- /dev/null +++ b/vendor/github.com/google/cel-go/checker/cost.go @@ -0,0 +1,601 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package checker + +import ( + "math" + + "github.com/google/cel-go/common" + "github.com/google/cel-go/common/overloads" + "github.com/google/cel-go/parser" + + exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" +) + +// WARNING: Any changes to cost calculations in this file require a corresponding change in interpreter/runtimecost.go + +// CostEstimator estimates the sizes of variable length input data and the costs of functions. +type CostEstimator interface { + // EstimateSize returns a SizeEstimate for the given AstNode, or nil if + // the estimator has no estimate to provide. The size is equivalent to the result of the CEL `size()` function: + // length of strings and bytes, number of map entries or number of list items. + // EstimateSize is only called for AstNodes where + // CEL does not know the size; EstimateSize is not called for values defined inline in CEL where the size + // is already obvious to CEL. + EstimateSize(element AstNode) *SizeEstimate + // EstimateCallCost returns the estimated cost of an invocation, or nil if + // the estimator has no estimate to provide. + EstimateCallCost(function, overloadID string, target *AstNode, args []AstNode) *CallEstimate +} + +// CallEstimate includes a CostEstimate for the call, and an optional estimate of the result object size. +// The ResultSize should only be provided if the call results in a map, list, string or bytes. +type CallEstimate struct { + CostEstimate + ResultSize *SizeEstimate +} + +// AstNode represents an AST node for the purpose of cost estimations. +type AstNode interface { + // Path returns a field path through the provided type declarations to the type of the AstNode, or nil if the AstNode does not + // represent type directly reachable from the provided type declarations. + // The first path element is a variable. All subsequent path elements are one of: field name, '@items', '@keys', '@values'. + Path() []string + // Type returns the deduced type of the AstNode. + Type() *exprpb.Type + // Expr returns the expression of the AstNode. + Expr() *exprpb.Expr + // ComputedSize returns a size estimate of the AstNode derived from information available in the CEL expression. + // For constants and inline list and map declarations, the exact size is returned. For concatenated list, strings + // and bytes, the size is derived from the size estimates of the operands. nil is returned if there is no + // computed size available. + ComputedSize() *SizeEstimate +} + +type astNode struct { + path []string + t *exprpb.Type + expr *exprpb.Expr + derivedSize *SizeEstimate +} + +func (e astNode) Path() []string { + return e.path +} + +func (e astNode) Type() *exprpb.Type { + return e.t +} + +func (e astNode) Expr() *exprpb.Expr { + return e.expr +} + +func (e astNode) ComputedSize() *SizeEstimate { + if e.derivedSize != nil { + return e.derivedSize + } + var v uint64 + switch ek := e.expr.ExprKind.(type) { + case *exprpb.Expr_ConstExpr: + switch ck := ek.ConstExpr.ConstantKind.(type) { + case *exprpb.Constant_StringValue: + v = uint64(len(ck.StringValue)) + case *exprpb.Constant_BytesValue: + v = uint64(len(ck.BytesValue)) + case *exprpb.Constant_BoolValue, *exprpb.Constant_DoubleValue, *exprpb.Constant_DurationValue, + *exprpb.Constant_Int64Value, *exprpb.Constant_TimestampValue, *exprpb.Constant_Uint64Value, + *exprpb.Constant_NullValue: + v = uint64(1) + default: + return nil + } + case *exprpb.Expr_ListExpr: + v = uint64(len(ek.ListExpr.Elements)) + case *exprpb.Expr_StructExpr: + if ek.StructExpr.MessageName == "" { + v = uint64(len(ek.StructExpr.Entries)) + } + default: + return nil + } + + return &SizeEstimate{Min: v, Max: v} +} + +// SizeEstimate represents an estimated size of a variable length string, bytes, map or list. +type SizeEstimate struct { + Min, Max uint64 +} + +// Add adds to another SizeEstimate and returns the sum. +// If add would result in an uint64 overflow, the result is math.MaxUint64. +func (se SizeEstimate) Add(sizeEstimate SizeEstimate) SizeEstimate { + return SizeEstimate{ + addUint64NoOverflow(se.Min, sizeEstimate.Min), + addUint64NoOverflow(se.Max, sizeEstimate.Max), + } +} + +// Multiply multiplies by another SizeEstimate and returns the product. +// If multiply would result in an uint64 overflow, the result is math.MaxUint64. +func (se SizeEstimate) Multiply(sizeEstimate SizeEstimate) SizeEstimate { + return SizeEstimate{ + multiplyUint64NoOverflow(se.Min, sizeEstimate.Min), + multiplyUint64NoOverflow(se.Max, sizeEstimate.Max), + } +} + +// MultiplyByCostFactor multiplies a SizeEstimate by a cost factor and returns the CostEstimate with the +// nearest integer of the result, rounded up. +func (se SizeEstimate) MultiplyByCostFactor(costPerUnit float64) CostEstimate { + return CostEstimate{ + multiplyByCostFactor(se.Min, costPerUnit), + multiplyByCostFactor(se.Max, costPerUnit), + } +} + +// MultiplyByCost multiplies by the cost and returns the product. +// If multiply would result in an uint64 overflow, the result is math.MaxUint64. +func (se SizeEstimate) MultiplyByCost(cost CostEstimate) CostEstimate { + return CostEstimate{ + multiplyUint64NoOverflow(se.Min, cost.Min), + multiplyUint64NoOverflow(se.Max, cost.Max), + } +} + +// Union returns a SizeEstimate that encompasses both input the SizeEstimate. +func (se SizeEstimate) Union(size SizeEstimate) SizeEstimate { + result := se + if size.Min < result.Min { + result.Min = size.Min + } + if size.Max > result.Max { + result.Max = size.Max + } + return result +} + +// CostEstimate represents an estimated cost range and provides add and multiply operations +// that do not overflow. +type CostEstimate struct { + Min, Max uint64 +} + +// Add adds the costs and returns the sum. +// If add would result in an uint64 overflow for the min or max, the value is set to math.MaxUint64. +func (ce CostEstimate) Add(cost CostEstimate) CostEstimate { + return CostEstimate{ + addUint64NoOverflow(ce.Min, cost.Min), + addUint64NoOverflow(ce.Max, cost.Max), + } +} + +// Multiply multiplies by the cost and returns the product. +// If multiply would result in an uint64 overflow, the result is math.MaxUint64. +func (ce CostEstimate) Multiply(cost CostEstimate) CostEstimate { + return CostEstimate{ + multiplyUint64NoOverflow(ce.Min, cost.Min), + multiplyUint64NoOverflow(ce.Max, cost.Max), + } +} + +// MultiplyByCostFactor multiplies a CostEstimate by a cost factor and returns the CostEstimate with the +// nearest integer of the result, rounded up. +func (ce CostEstimate) MultiplyByCostFactor(costPerUnit float64) CostEstimate { + return CostEstimate{ + multiplyByCostFactor(ce.Min, costPerUnit), + multiplyByCostFactor(ce.Max, costPerUnit), + } +} + +// Union returns a CostEstimate that encompasses both input the CostEstimates. +func (ce CostEstimate) Union(size CostEstimate) CostEstimate { + result := ce + if size.Min < result.Min { + result.Min = size.Min + } + if size.Max > result.Max { + result.Max = size.Max + } + return result +} + +// addUint64NoOverflow adds non-negative ints. If the result is exceeds math.MaxUint64, math.MaxUint64 +// is returned. +func addUint64NoOverflow(x, y uint64) uint64 { + if y > 0 && x > math.MaxUint64-y { + return math.MaxUint64 + } + return x + y +} + +// multiplyUint64NoOverflow multiplies non-negative ints. If the result is exceeds math.MaxUint64, math.MaxUint64 +// is returned. +func multiplyUint64NoOverflow(x, y uint64) uint64 { + if x > 0 && y > 0 && x > math.MaxUint64/y { + return math.MaxUint64 + } + return x * y +} + +// multiplyByFactor multiplies an integer by a cost factor float and returns the nearest integer value, rounded up. +func multiplyByCostFactor(x uint64, y float64) uint64 { + xFloat := float64(x) + if xFloat > 0 && y > 0 && xFloat > math.MaxUint64/y { + return math.MaxUint64 + } + return uint64(math.Ceil(xFloat * y)) +} + +var ( + selectAndIdentCost = CostEstimate{Min: common.SelectAndIdentCost, Max: common.SelectAndIdentCost} + constCost = CostEstimate{Min: common.ConstCost, Max: common.ConstCost} + + createListBaseCost = CostEstimate{Min: common.ListCreateBaseCost, Max: common.ListCreateBaseCost} + createMapBaseCost = CostEstimate{Min: common.MapCreateBaseCost, Max: common.MapCreateBaseCost} + createMessageBaseCost = CostEstimate{Min: common.StructCreateBaseCost, Max: common.StructCreateBaseCost} +) + +type coster struct { + // exprPath maps from Expr Id to field path. + exprPath map[int64][]string + // iterRanges tracks the iterRange of each iterVar. + iterRanges iterRangeScopes + // computedSizes tracks the computed sizes of call results. + computedSizes map[int64]SizeEstimate + checkedExpr *exprpb.CheckedExpr + estimator CostEstimator +} + +// Use a stack of iterVar -> iterRange Expr Ids to handle shadowed variable names. +type iterRangeScopes map[string][]int64 + +func (vs iterRangeScopes) push(varName string, expr *exprpb.Expr) { + vs[varName] = append(vs[varName], expr.GetId()) +} + +func (vs iterRangeScopes) pop(varName string) { + varStack := vs[varName] + vs[varName] = varStack[:len(varStack)-1] +} + +func (vs iterRangeScopes) peek(varName string) (int64, bool) { + varStack := vs[varName] + if len(varStack) > 0 { + return varStack[len(varStack)-1], true + } + return 0, false +} + +// Cost estimates the cost of the parsed and type checked CEL expression. +func Cost(checker *exprpb.CheckedExpr, estimator CostEstimator) CostEstimate { + c := coster{ + checkedExpr: checker, + estimator: estimator, + exprPath: map[int64][]string{}, + iterRanges: map[string][]int64{}, + computedSizes: map[int64]SizeEstimate{}, + } + return c.cost(checker.GetExpr()) +} + +func (c *coster) cost(e *exprpb.Expr) CostEstimate { + if e == nil { + return CostEstimate{} + } + var cost CostEstimate + switch e.ExprKind.(type) { + case *exprpb.Expr_ConstExpr: + cost = constCost + case *exprpb.Expr_IdentExpr: + cost = c.costIdent(e) + case *exprpb.Expr_SelectExpr: + cost = c.costSelect(e) + case *exprpb.Expr_CallExpr: + cost = c.costCall(e) + case *exprpb.Expr_ListExpr: + cost = c.costCreateList(e) + case *exprpb.Expr_StructExpr: + cost = c.costCreateStruct(e) + case *exprpb.Expr_ComprehensionExpr: + cost = c.costComprehension(e) + default: + return CostEstimate{} + } + return cost +} + +func (c *coster) costIdent(e *exprpb.Expr) CostEstimate { + identExpr := e.GetIdentExpr() + + // build and track the field path + if iterRange, ok := c.iterRanges.peek(identExpr.GetName()); ok { + switch c.checkedExpr.TypeMap[iterRange].TypeKind.(type) { + case *exprpb.Type_ListType_: + c.addPath(e, append(c.exprPath[iterRange], "@items")) + case *exprpb.Type_MapType_: + c.addPath(e, append(c.exprPath[iterRange], "@keys")) + } + } else { + c.addPath(e, []string{identExpr.GetName()}) + } + + return selectAndIdentCost +} + +func (c *coster) costSelect(e *exprpb.Expr) CostEstimate { + sel := e.GetSelectExpr() + var sum CostEstimate + if sel.GetTestOnly() { + return sum + } + sum = sum.Add(c.cost(sel.GetOperand())) + targetType := c.getType(sel.GetOperand()) + switch kindOf(targetType) { + case kindMap, kindObject, kindTypeParam: + sum = sum.Add(selectAndIdentCost) + } + + // build and track the field path + c.addPath(e, append(c.getPath(sel.GetOperand()), sel.Field)) + + return sum +} + +func (c *coster) costCall(e *exprpb.Expr) CostEstimate { + call := e.GetCallExpr() + target := call.GetTarget() + args := call.GetArgs() + + var sum CostEstimate + + argTypes := make([]AstNode, len(args)) + argCosts := make([]CostEstimate, len(args)) + for i, arg := range args { + argCosts[i] = c.cost(arg) + argTypes[i] = c.newAstNode(arg) + } + + ref := c.checkedExpr.ReferenceMap[e.GetId()] + if ref == nil || len(ref.GetOverloadId()) == 0 { + return CostEstimate{} + } + var targetType AstNode + if target != nil { + if call.Target != nil { + sum = sum.Add(c.cost(call.GetTarget())) + targetType = c.newAstNode(call.GetTarget()) + } + } + // Pick a cost estimate range that covers all the overload cost estimation ranges + fnCost := CostEstimate{Min: uint64(math.MaxUint64), Max: 0} + var resultSize *SizeEstimate + for _, overload := range ref.GetOverloadId() { + overloadCost := c.functionCost(call.GetFunction(), overload, &targetType, argTypes, argCosts) + fnCost = fnCost.Union(overloadCost.CostEstimate) + if overloadCost.ResultSize != nil { + if resultSize == nil { + resultSize = overloadCost.ResultSize + } else { + size := resultSize.Union(*overloadCost.ResultSize) + resultSize = &size + } + } + // build and track the field path for index operations + switch overload { + case overloads.IndexList: + if len(args) > 0 { + c.addPath(e, append(c.getPath(args[0]), "@items")) + } + case overloads.IndexMap: + if len(args) > 0 { + c.addPath(e, append(c.getPath(args[0]), "@values")) + } + } + } + if resultSize != nil { + c.computedSizes[e.GetId()] = *resultSize + } + return sum.Add(fnCost) +} + +func (c *coster) costCreateList(e *exprpb.Expr) CostEstimate { + create := e.GetListExpr() + var sum CostEstimate + for _, e := range create.GetElements() { + sum = sum.Add(c.cost(e)) + } + return sum.Add(createListBaseCost) +} + +func (c *coster) costCreateStruct(e *exprpb.Expr) CostEstimate { + str := e.GetStructExpr() + if str.MessageName != "" { + return c.costCreateMessage(e) + } + return c.costCreateMap(e) +} + +func (c *coster) costCreateMap(e *exprpb.Expr) CostEstimate { + mapVal := e.GetStructExpr() + var sum CostEstimate + for _, ent := range mapVal.GetEntries() { + key := ent.GetMapKey() + sum = sum.Add(c.cost(key)) + + sum = sum.Add(c.cost(ent.GetValue())) + } + return sum.Add(createMapBaseCost) +} + +func (c *coster) costCreateMessage(e *exprpb.Expr) CostEstimate { + msgVal := e.GetStructExpr() + var sum CostEstimate + for _, ent := range msgVal.GetEntries() { + sum = sum.Add(c.cost(ent.GetValue())) + } + return sum.Add(createMessageBaseCost) +} + +func (c *coster) costComprehension(e *exprpb.Expr) CostEstimate { + comp := e.GetComprehensionExpr() + var sum CostEstimate + sum = sum.Add(c.cost(comp.GetIterRange())) + sum = sum.Add(c.cost(comp.GetAccuInit())) + + // Track the iterRange of each IterVar for field path construction + c.iterRanges.push(comp.GetIterVar(), comp.GetIterRange()) + loopCost := c.cost(comp.GetLoopCondition()) + stepCost := c.cost(comp.GetLoopStep()) + c.iterRanges.pop(comp.GetIterVar()) + sum = sum.Add(c.cost(comp.Result)) + rangeCnt := c.sizeEstimate(c.newAstNode(comp.GetIterRange())) + rangeCost := rangeCnt.MultiplyByCost(stepCost.Add(loopCost)) + sum = sum.Add(rangeCost) + + return sum +} + +func (c *coster) sizeEstimate(t AstNode) SizeEstimate { + if l := t.ComputedSize(); l != nil { + return *l + } + if l := c.estimator.EstimateSize(t); l != nil { + return *l + } + return SizeEstimate{Min: 0, Max: math.MaxUint64} +} + +func (c *coster) functionCost(function, overloadID string, target *AstNode, args []AstNode, argCosts []CostEstimate) CallEstimate { + argCostSum := func() CostEstimate { + var sum CostEstimate + for _, a := range argCosts { + sum = sum.Add(a) + } + return sum + } + + if est := c.estimator.EstimateCallCost(function, overloadID, target, args); est != nil { + callEst := *est + return CallEstimate{CostEstimate: callEst.Add(argCostSum())} + } + switch overloadID { + // O(n) functions + case overloads.StartsWithString, overloads.EndsWithString, overloads.StringToBytes, overloads.BytesToString: + if len(args) == 1 { + return CallEstimate{CostEstimate: c.sizeEstimate(args[0]).MultiplyByCostFactor(common.StringTraversalCostFactor).Add(argCostSum())} + } + case overloads.InList: + // If a list is composed entirely of constant values this is O(1), but we don't account for that here. + // We just assume all list containment checks are O(n). + if len(args) == 2 { + return CallEstimate{CostEstimate: c.sizeEstimate(args[1]).MultiplyByCostFactor(1).Add(argCostSum())} + } + // O(nm) functions + case overloads.MatchesString: + // https://swtch.com/~rsc/regexp/regexp1.html applies to RE2 implementation supported by CEL + if target != nil && len(args) == 1 { + // Add one to string length for purposes of cost calculation to prevent product of string and regex to be 0 + // in case where string is empty but regex is still expensive. + strCost := c.sizeEstimate(*target).Add(SizeEstimate{Min: 1, Max: 1}).MultiplyByCostFactor(common.StringTraversalCostFactor) + // We don't know how many expressions are in the regex, just the string length (a huge + // improvement here would be to somehow get a count the number of expressions in the regex or + // how many states are in the regex state machine and use that to measure regex cost). + // For now, we're making a guess that each expression in a regex is typically at least 4 chars + // in length. + regexCost := c.sizeEstimate(args[0]).MultiplyByCostFactor(common.RegexStringLengthCostFactor) + return CallEstimate{CostEstimate: strCost.Multiply(regexCost).Add(argCostSum())} + } + case overloads.ContainsString: + if target != nil && len(args) == 1 { + strCost := c.sizeEstimate(*target).MultiplyByCostFactor(common.StringTraversalCostFactor) + substrCost := c.sizeEstimate(args[0]).MultiplyByCostFactor(common.StringTraversalCostFactor) + return CallEstimate{CostEstimate: strCost.Multiply(substrCost).Add(argCostSum())} + } + case overloads.LogicalOr, overloads.LogicalAnd: + lhs := argCosts[0] + rhs := argCosts[1] + // min cost is min of LHS for short circuited && or || + argCost := CostEstimate{Min: lhs.Min, Max: lhs.Add(rhs).Max} + return CallEstimate{CostEstimate: argCost} + case overloads.Conditional: + size := c.sizeEstimate(args[1]).Union(c.sizeEstimate(args[2])) + conditionalCost := argCosts[0] + ifTrueCost := argCosts[1] + ifFalseCost := argCosts[2] + argCost := conditionalCost.Add(ifTrueCost.Union(ifFalseCost)) + return CallEstimate{CostEstimate: argCost, ResultSize: &size} + case overloads.AddString, overloads.AddBytes, overloads.AddList: + if len(args) == 2 { + lhsSize := c.sizeEstimate(args[0]) + rhsSize := c.sizeEstimate(args[1]) + resultSize := lhsSize.Add(rhsSize) + switch overloadID { + case overloads.AddList: + // list concatenation is O(1), but we handle it here to track size + return CallEstimate{CostEstimate: CostEstimate{Min: 1, Max: 1}.Add(argCostSum()), ResultSize: &resultSize} + default: + return CallEstimate{CostEstimate: resultSize.MultiplyByCostFactor(common.StringTraversalCostFactor).Add(argCostSum()), ResultSize: &resultSize} + } + } + case overloads.LessString, overloads.GreaterString, overloads.LessEqualsString, overloads.GreaterEqualsString, + overloads.LessBytes, overloads.GreaterBytes, overloads.LessEqualsBytes, overloads.GreaterEqualsBytes, + overloads.Equals, overloads.NotEquals: + lhsCost := c.sizeEstimate(args[0]) + rhsCost := c.sizeEstimate(args[1]) + min := uint64(0) + smallestMax := lhsCost.Max + if rhsCost.Max < smallestMax { + smallestMax = rhsCost.Max + } + if smallestMax > 0 { + min = 1 + } + // equality of 2 scalar values results in a cost of 1 + return CallEstimate{CostEstimate: CostEstimate{Min: min, Max: smallestMax}.MultiplyByCostFactor(common.StringTraversalCostFactor).Add(argCostSum())} + } + // O(1) functions + // See CostTracker.costCall for more details about O(1) cost calculations + + // Benchmarks suggest that most of the other operations take +/- 50% of a base cost unit + // which on an Intel xeon 2.20GHz CPU is 50ns. + return CallEstimate{CostEstimate: CostEstimate{Min: 1, Max: 1}.Add(argCostSum())} +} + +func (c *coster) getType(e *exprpb.Expr) *exprpb.Type { + return c.checkedExpr.TypeMap[e.GetId()] +} + +func (c *coster) getPath(e *exprpb.Expr) []string { + return c.exprPath[e.GetId()] +} + +func (c *coster) addPath(e *exprpb.Expr, path []string) { + c.exprPath[e.GetId()] = path +} + +func (c *coster) newAstNode(e *exprpb.Expr) *astNode { + path := c.getPath(e) + if len(path) > 0 && path[0] == parser.AccumulatorName { + // only provide paths to root vars; omit accumulator vars + path = nil + } + var derivedSize *SizeEstimate + if size, ok := c.computedSizes[e.GetId()]; ok { + derivedSize = &size + } + return &astNode{path: path, t: c.getType(e), expr: e, derivedSize: derivedSize} +} diff --git a/vendor/github.com/google/cel-go/checker/decls/scopes.go b/vendor/github.com/google/cel-go/checker/decls/scopes.go index 1064c73b1..608bca3e5 100644 --- a/vendor/github.com/google/cel-go/checker/decls/scopes.go +++ b/vendor/github.com/google/cel-go/checker/decls/scopes.go @@ -33,6 +33,19 @@ func NewScopes() *Scopes { } } +// Copy creates a copy of the current Scopes values, including a copy of its parent if non-nil. +func (s *Scopes) Copy() *Scopes { + cpy := NewScopes() + if s == nil { + return cpy + } + if s.parent != nil { + cpy.parent = s.parent.Copy() + } + cpy.scopes = s.scopes.copy() + return cpy +} + // Push creates a new Scopes value which references the current Scope as its parent. func (s *Scopes) Push() *Scopes { return &Scopes{ @@ -80,9 +93,9 @@ func (s *Scopes) FindIdentInScope(name string) *exprpb.Decl { return nil } -// AddFunction adds the function Decl to the current scope. +// SetFunction adds the function Decl to the current scope. // Note: Any previous entry for a function in the current scope with the same name is overwritten. -func (s *Scopes) AddFunction(fn *exprpb.Decl) { +func (s *Scopes) SetFunction(fn *exprpb.Decl) { s.scopes.functions[fn.Name] = fn } @@ -100,13 +113,30 @@ func (s *Scopes) FindFunction(name string) *exprpb.Decl { } // Group is a set of Decls that is pushed on or popped off a Scopes as a unit. -// Contains separate namespaces for idenifier and function Decls. +// Contains separate namespaces for identifier and function Decls. // (Should be named "Scope" perhaps?) type Group struct { idents map[string]*exprpb.Decl functions map[string]*exprpb.Decl } +// copy creates a new Group instance with a shallow copy of the variables and functions. +// If callers need to mutate the exprpb.Decl definitions for a Function, they should copy-on-write. +func (g *Group) copy() *Group { + cpy := &Group{ + idents: make(map[string]*exprpb.Decl, len(g.idents)), + functions: make(map[string]*exprpb.Decl, len(g.functions)), + } + for n, id := range g.idents { + cpy.idents[n] = id + } + for n, fn := range g.functions { + cpy.functions[n] = fn + } + return cpy +} + +// newGroup creates a new Group with empty maps for identifiers and functions. func newGroup() *Group { return &Group{ idents: make(map[string]*exprpb.Decl), diff --git a/vendor/github.com/google/cel-go/checker/env.go b/vendor/github.com/google/cel-go/checker/env.go index 93cb10612..c9d0614e3 100644 --- a/vendor/github.com/google/cel-go/checker/env.go +++ b/vendor/github.com/google/cel-go/checker/env.go @@ -18,8 +18,11 @@ import ( "fmt" "strings" + "google.golang.org/protobuf/proto" + "github.com/google/cel-go/checker/decls" "github.com/google/cel-go/common/containers" + "github.com/google/cel-go/common/overloads" "github.com/google/cel-go/common/types" "github.com/google/cel-go/common/types/pb" "github.com/google/cel-go/common/types/ref" @@ -35,49 +38,79 @@ const ( homogenousElementType aggregateLiteralElementType = 1 << iota ) +var ( + crossTypeNumericComparisonOverloads = map[string]struct{}{ + // double <-> int | uint + overloads.LessDoubleInt64: {}, + overloads.LessDoubleUint64: {}, + overloads.LessEqualsDoubleInt64: {}, + overloads.LessEqualsDoubleUint64: {}, + overloads.GreaterDoubleInt64: {}, + overloads.GreaterDoubleUint64: {}, + overloads.GreaterEqualsDoubleInt64: {}, + overloads.GreaterEqualsDoubleUint64: {}, + // int <-> double | uint + overloads.LessInt64Double: {}, + overloads.LessInt64Uint64: {}, + overloads.LessEqualsInt64Double: {}, + overloads.LessEqualsInt64Uint64: {}, + overloads.GreaterInt64Double: {}, + overloads.GreaterInt64Uint64: {}, + overloads.GreaterEqualsInt64Double: {}, + overloads.GreaterEqualsInt64Uint64: {}, + // uint <-> double | int + overloads.LessUint64Double: {}, + overloads.LessUint64Int64: {}, + overloads.LessEqualsUint64Double: {}, + overloads.LessEqualsUint64Int64: {}, + overloads.GreaterUint64Double: {}, + overloads.GreaterUint64Int64: {}, + overloads.GreaterEqualsUint64Double: {}, + overloads.GreaterEqualsUint64Int64: {}, + } +) + // Env is the environment for type checking. // // The Env is comprised of a container, type provider, declarations, and other related objects // which can be used to assist with type-checking. type Env struct { - container *containers.Container - provider ref.TypeProvider - declarations *decls.Scopes - aggLitElemType aggregateLiteralElementType + container *containers.Container + provider ref.TypeProvider + declarations *decls.Scopes + aggLitElemType aggregateLiteralElementType + filteredOverloadIDs map[string]struct{} } // NewEnv returns a new *Env with the given parameters. -func NewEnv(container *containers.Container, provider ref.TypeProvider) *Env { +func NewEnv(container *containers.Container, provider ref.TypeProvider, opts ...Option) (*Env, error) { declarations := decls.NewScopes() declarations.Push() + envOptions := &options{} + for _, opt := range opts { + if err := opt(envOptions); err != nil { + return nil, err + } + } + aggLitElemType := dynElementType + if envOptions.homogeneousAggregateLiterals { + aggLitElemType = homogenousElementType + } + filteredOverloadIDs := crossTypeNumericComparisonOverloads + if envOptions.crossTypeNumericComparisons { + filteredOverloadIDs = make(map[string]struct{}) + } + if envOptions.validatedDeclarations != nil { + declarations = envOptions.validatedDeclarations.Copy() + } return &Env{ - container: container, - provider: provider, - declarations: declarations, - } -} - -// NewStandardEnv returns a new *Env with the given params plus standard declarations. -func NewStandardEnv(container *containers.Container, provider ref.TypeProvider) *Env { - e := NewEnv(container, provider) - if err := e.Add(StandardDeclarations()...); err != nil { - // The standard declaration set should never have duplicate declarations. - panic(err) - } - // TODO: isolate standard declarations from the custom set which may be provided layer. - return e -} - -// EnableDynamicAggregateLiterals detmerines whether list and map literals may support mixed -// element types at check-time. This does not preclude the presence of a dynamic list or map -// somewhere in the CEL evaluation process. -func (e *Env) EnableDynamicAggregateLiterals(enabled bool) *Env { - e.aggLitElemType = dynElementType - if !enabled { - e.aggLitElemType = homogenousElementType - } - return e + container: container, + provider: provider, + declarations: declarations, + aggLitElemType: aggLitElemType, + filteredOverloadIDs: filteredOverloadIDs, + }, nil } // Add adds new Decl protos to the Env. @@ -89,7 +122,7 @@ func (e *Env) Add(decls ...*exprpb.Decl) error { case *exprpb.Decl_Ident: errMsgs = append(errMsgs, e.addIdent(sanitizeIdent(decl))) case *exprpb.Decl_Function: - errMsgs = append(errMsgs, e.addFunction(sanitizeFunction(decl))...) + errMsgs = append(errMsgs, e.setFunction(sanitizeFunction(decl))...) } } return formatError(errMsgs) @@ -176,16 +209,19 @@ func (e *Env) addOverload(f *exprpb.Decl, overload *exprpb.Decl_FunctionDecl_Ove return errMsgs } -// addFunction adds the function Decl to the Env. +// setFunction adds the function Decl to the Env. // Adds a function decl if one doesn't already exist, then adds all overloads from the Decl. // If overload overlaps with an existing overload, adds to the errors in the Env instead. -func (e *Env) addFunction(decl *exprpb.Decl) []errorMsg { +func (e *Env) setFunction(decl *exprpb.Decl) []errorMsg { current := e.declarations.FindFunction(decl.Name) if current == nil { //Add the function declaration without overloads and check the overloads below. current = decls.NewFunction(decl.Name) - e.declarations.AddFunction(current) + } else { + // Copy on write since we don't know where this original definition came from. + current = proto.Clone(current).(*exprpb.Decl) } + e.declarations.SetFunction(current) errorMsgs := make([]errorMsg, 0) for _, overload := range decl.GetFunction().GetOverloads() { @@ -205,6 +241,12 @@ func (e *Env) addIdent(decl *exprpb.Decl) errorMsg { return "" } +// isOverloadDisabled returns whether the overloadID is disabled in the current environment. +func (e *Env) isOverloadDisabled(overloadID string) bool { + _, found := e.filteredOverloadIDs[overloadID] + return found +} + // sanitizeFunction replaces well-known types referenced by message name with their equivalent // CEL built-in type instances. func sanitizeFunction(decl *exprpb.Decl) *exprpb.Decl { @@ -231,34 +273,26 @@ func sanitizeFunction(decl *exprpb.Decl) *exprpb.Decl { } // Sanitize all of the overloads if any overload requires an update to its type references. - overloads := make([]*exprpb.Decl_FunctionDecl_Overload, 0, len(fn.GetOverloads())) + overloads := make([]*exprpb.Decl_FunctionDecl_Overload, len(fn.GetOverloads())) for i, o := range fn.GetOverloads() { - var sanitized bool rt := o.GetResultType() if isObjectWellKnownType(rt) { rt = getObjectWellKnownType(rt) - sanitized = true } - params := make([]*exprpb.Type, 0, len(o.GetParams())) + params := make([]*exprpb.Type, len(o.GetParams())) copy(params, o.GetParams()) for j, p := range params { if isObjectWellKnownType(p) { params[j] = getObjectWellKnownType(p) - sanitized = true } } // If sanitized, replace the overload definition. - if sanitized { - if o.IsInstanceFunction { - overloads[i] = - decls.NewInstanceOverload(o.GetOverloadId(), params, rt) - } else { - overloads[i] = - decls.NewOverload(o.GetOverloadId(), params, rt) - } + if o.IsInstanceFunction { + overloads[i] = + decls.NewInstanceOverload(o.GetOverloadId(), params, rt) } else { - // Otherwise, preserve the original overload. - overloads[i] = o + overloads[i] = + decls.NewOverload(o.GetOverloadId(), params, rt) } } return decls.NewFunction(decl.GetName(), overloads...) @@ -290,6 +324,12 @@ func getObjectWellKnownType(t *exprpb.Type) *exprpb.Type { return pb.CheckedWellKnowns[t.GetMessageType()] } +// validatedDeclarations returns a reference to the validated variable and function declaration scope stack. +// must be copied before use. +func (e *Env) validatedDeclarations() *decls.Scopes { + return e.declarations +} + // enterScope creates a new Env instance with a new innermost declaration scope. func (e *Env) enterScope() *Env { childDecls := e.declarations.Push() diff --git a/vendor/github.com/google/cel-go/checker/errors.go b/vendor/github.com/google/cel-go/checker/errors.go index 33af57cd2..0014f9abe 100644 --- a/vendor/github.com/google/cel-go/checker/errors.go +++ b/vendor/github.com/google/cel-go/checker/errors.go @@ -29,10 +29,6 @@ func (e *typeErrors) undeclaredReference(l common.Location, container string, na e.ReportError(l, "undeclared reference to '%s' (in container '%s')", name, container) } -func (e *typeErrors) expressionDoesNotSelectField(l common.Location) { - e.ReportError(l, "expression does not select a field") -} - func (e *typeErrors) typeDoesNotSupportFieldSelection(l common.Location, t *exprpb.Type) { e.ReportError(l, "type '%s' does not support field selection", t) } @@ -41,34 +37,11 @@ func (e *typeErrors) undefinedField(l common.Location, field string) { e.ReportError(l, "undefined field '%s'", field) } -func (e *typeErrors) fieldDoesNotSupportPresenceCheck(l common.Location, field string) { - e.ReportError(l, "field '%s' does not support presence check", field) -} - -func (e *typeErrors) overlappingOverload(l common.Location, name string, overloadID1 string, f1 *exprpb.Type, - overloadID2 string, f2 *exprpb.Type) { - e.ReportError(l, "overlapping overload for name '%s' (type '%s' with overloadId: '%s' cannot be distinguished from '%s' with "+ - "overloadId: '%s')", name, FormatCheckedType(f1), overloadID1, FormatCheckedType(f2), overloadID2) -} - -func (e *typeErrors) overlappingMacro(l common.Location, name string, args int) { - e.ReportError(l, "overload for name '%s' with %d argument(s) overlaps with predefined macro", - name, args) -} - func (e *typeErrors) noMatchingOverload(l common.Location, name string, args []*exprpb.Type, isInstance bool) { signature := formatFunction(nil, args, isInstance) e.ReportError(l, "found no matching overload for '%s' applied to '%s'", name, signature) } -func (e *typeErrors) aggregateTypeMismatch(l common.Location, aggregate *exprpb.Type, member *exprpb.Type) { - e.ReportError( - l, - "type '%s' does not match previous type '%s' in aggregate. Use 'dyn(x)' to make the aggregate dynamic.", - FormatCheckedType(member), - FormatCheckedType(aggregate)) -} - func (e *typeErrors) notAType(l common.Location, t *exprpb.Type) { e.ReportError(l, "'%s(%v)' is not a type", FormatCheckedType(t), t) } diff --git a/vendor/github.com/google/cel-go/checker/mapping.go b/vendor/github.com/google/cel-go/checker/mapping.go index bd5e412db..fbc55a28d 100644 --- a/vendor/github.com/google/cel-go/checker/mapping.go +++ b/vendor/github.com/google/cel-go/checker/mapping.go @@ -15,8 +15,6 @@ package checker import ( - "fmt" - exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" ) @@ -49,14 +47,3 @@ func (m *mapping) copy() *mapping { } return c } - -func (m *mapping) String() string { - result := "{" - - for k, v := range m.mapping { - result += fmt.Sprintf("%v => %v ", k, v) - } - - result += "}" - return result -} diff --git a/vendor/github.com/google/cel-go/checker/options.go b/vendor/github.com/google/cel-go/checker/options.go new file mode 100644 index 000000000..cded00a66 --- /dev/null +++ b/vendor/github.com/google/cel-go/checker/options.go @@ -0,0 +1,53 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package checker + +import "github.com/google/cel-go/checker/decls" + +type options struct { + crossTypeNumericComparisons bool + homogeneousAggregateLiterals bool + validatedDeclarations *decls.Scopes +} + +// Option is a functional option for configuring the type-checker +type Option func(*options) error + +// CrossTypeNumericComparisons toggles type-checker support for numeric comparisons across type +// See https://github.com/google/cel-spec/wiki/proposal-210 for more details. +func CrossTypeNumericComparisons(enabled bool) Option { + return func(opts *options) error { + opts.crossTypeNumericComparisons = enabled + return nil + } +} + +// HomogeneousAggregateLiterals toggles support for constructing lists and maps whose elements all +// have the same type. +func HomogeneousAggregateLiterals(enabled bool) Option { + return func(opts *options) error { + opts.homogeneousAggregateLiterals = enabled + return nil + } +} + +// ValidatedDeclarations provides a references to validated declarations which will be copied +// into new checker instances. +func ValidatedDeclarations(env *Env) Option { + return func(opts *options) error { + opts.validatedDeclarations = env.validatedDeclarations() + return nil + } +} diff --git a/vendor/github.com/google/cel-go/checker/standard.go b/vendor/github.com/google/cel-go/checker/standard.go index 769de7511..5b48a9046 100644 --- a/vendor/github.com/google/cel-go/checker/standard.go +++ b/vendor/github.com/google/cel-go/checker/standard.go @@ -22,8 +22,11 @@ import ( exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" ) -// StandardDeclarations returns the Decls for all functions and constants in the evaluator. -func StandardDeclarations() []*exprpb.Decl { +var ( + standardDeclarations []*exprpb.Decl +) + +func init() { // Some shortcuts we use when building declarations. paramA := decls.NewTypeParamType("A") typeParamAList := []string{"A"} @@ -45,9 +48,9 @@ func StandardDeclarations() []*exprpb.Decl { decls.NewVar("null_type", decls.NewTypeType(decls.Null)), decls.NewVar("type", decls.NewTypeType(decls.NewTypeType(nil)))) - // Booleans - // TODO: allow the conditional to return a heterogenous type. - return append(idents, []*exprpb.Decl{ + standardDeclarations = append(standardDeclarations, idents...) + standardDeclarations = append(standardDeclarations, []*exprpb.Decl{ + // Booleans decls.NewFunction(operators.Conditional, decls.NewParameterizedOverload(overloads.Conditional, []*exprpb.Type{decls.Bool, paramA, paramA}, paramA, @@ -69,80 +72,6 @@ func StandardDeclarations() []*exprpb.Decl { decls.NewOverload(overloads.NotStrictlyFalse, []*exprpb.Type{decls.Bool}, decls.Bool)), - // Relations. - - decls.NewFunction(operators.Less, - decls.NewOverload(overloads.LessBool, - []*exprpb.Type{decls.Bool, decls.Bool}, decls.Bool), - decls.NewOverload(overloads.LessInt64, - []*exprpb.Type{decls.Int, decls.Int}, decls.Bool), - decls.NewOverload(overloads.LessUint64, - []*exprpb.Type{decls.Uint, decls.Uint}, decls.Bool), - decls.NewOverload(overloads.LessDouble, - []*exprpb.Type{decls.Double, decls.Double}, decls.Bool), - decls.NewOverload(overloads.LessString, - []*exprpb.Type{decls.String, decls.String}, decls.Bool), - decls.NewOverload(overloads.LessBytes, - []*exprpb.Type{decls.Bytes, decls.Bytes}, decls.Bool), - decls.NewOverload(overloads.LessTimestamp, - []*exprpb.Type{decls.Timestamp, decls.Timestamp}, decls.Bool), - decls.NewOverload(overloads.LessDuration, - []*exprpb.Type{decls.Duration, decls.Duration}, decls.Bool)), - - decls.NewFunction(operators.LessEquals, - decls.NewOverload(overloads.LessEqualsBool, - []*exprpb.Type{decls.Bool, decls.Bool}, decls.Bool), - decls.NewOverload(overloads.LessEqualsInt64, - []*exprpb.Type{decls.Int, decls.Int}, decls.Bool), - decls.NewOverload(overloads.LessEqualsUint64, - []*exprpb.Type{decls.Uint, decls.Uint}, decls.Bool), - decls.NewOverload(overloads.LessEqualsDouble, - []*exprpb.Type{decls.Double, decls.Double}, decls.Bool), - decls.NewOverload(overloads.LessEqualsString, - []*exprpb.Type{decls.String, decls.String}, decls.Bool), - decls.NewOverload(overloads.LessEqualsBytes, - []*exprpb.Type{decls.Bytes, decls.Bytes}, decls.Bool), - decls.NewOverload(overloads.LessEqualsTimestamp, - []*exprpb.Type{decls.Timestamp, decls.Timestamp}, decls.Bool), - decls.NewOverload(overloads.LessEqualsDuration, - []*exprpb.Type{decls.Duration, decls.Duration}, decls.Bool)), - - decls.NewFunction(operators.Greater, - decls.NewOverload(overloads.GreaterBool, - []*exprpb.Type{decls.Bool, decls.Bool}, decls.Bool), - decls.NewOverload(overloads.GreaterInt64, - []*exprpb.Type{decls.Int, decls.Int}, decls.Bool), - decls.NewOverload(overloads.GreaterUint64, - []*exprpb.Type{decls.Uint, decls.Uint}, decls.Bool), - decls.NewOverload(overloads.GreaterDouble, - []*exprpb.Type{decls.Double, decls.Double}, decls.Bool), - decls.NewOverload(overloads.GreaterString, - []*exprpb.Type{decls.String, decls.String}, decls.Bool), - decls.NewOverload(overloads.GreaterBytes, - []*exprpb.Type{decls.Bytes, decls.Bytes}, decls.Bool), - decls.NewOverload(overloads.GreaterTimestamp, - []*exprpb.Type{decls.Timestamp, decls.Timestamp}, decls.Bool), - decls.NewOverload(overloads.GreaterDuration, - []*exprpb.Type{decls.Duration, decls.Duration}, decls.Bool)), - - decls.NewFunction(operators.GreaterEquals, - decls.NewOverload(overloads.GreaterEqualsBool, - []*exprpb.Type{decls.Bool, decls.Bool}, decls.Bool), - decls.NewOverload(overloads.GreaterEqualsInt64, - []*exprpb.Type{decls.Int, decls.Int}, decls.Bool), - decls.NewOverload(overloads.GreaterEqualsUint64, - []*exprpb.Type{decls.Uint, decls.Uint}, decls.Bool), - decls.NewOverload(overloads.GreaterEqualsDouble, - []*exprpb.Type{decls.Double, decls.Double}, decls.Bool), - decls.NewOverload(overloads.GreaterEqualsString, - []*exprpb.Type{decls.String, decls.String}, decls.Bool), - decls.NewOverload(overloads.GreaterEqualsBytes, - []*exprpb.Type{decls.Bytes, decls.Bytes}, decls.Bool), - decls.NewOverload(overloads.GreaterEqualsTimestamp, - []*exprpb.Type{decls.Timestamp, decls.Timestamp}, decls.Bool), - decls.NewOverload(overloads.GreaterEqualsDuration, - []*exprpb.Type{decls.Duration, decls.Duration}, decls.Bool)), - decls.NewFunction(operators.Equals, decls.NewParameterizedOverload(overloads.Equals, []*exprpb.Type{paramA, paramA}, decls.Bool, @@ -227,8 +156,6 @@ func StandardDeclarations() []*exprpb.Decl { decls.NewParameterizedOverload(overloads.IndexMap, []*exprpb.Type{mapOfAB, paramA}, paramB, typeParamABList)), - //decls.NewOverload(overloads.IndexMessage, - // []*expr.Type{decls.Dyn, decls.String}, decls.Dyn)), // Collections. @@ -267,8 +194,6 @@ func StandardDeclarations() []*exprpb.Decl { decls.NewParameterizedOverload(overloads.InMap, []*exprpb.Type{paramA, mapOfAB}, decls.Bool, typeParamABList)), - //decls.NewOverload(overloads.InMessage, - // []*expr.Type{Dyn, decls.String},decls.Bool)), // Conversions to type. @@ -436,5 +361,132 @@ func StandardDeclarations() []*exprpb.Decl { decls.NewInstanceOverload(overloads.TimestampToMillisecondsWithTz, []*exprpb.Type{decls.Timestamp, decls.String}, decls.Int), decls.NewInstanceOverload(overloads.DurationToMilliseconds, - []*exprpb.Type{decls.Duration}, decls.Int))}...) + []*exprpb.Type{decls.Duration}, decls.Int)), + + // Relations. + decls.NewFunction(operators.Less, + decls.NewOverload(overloads.LessBool, + []*exprpb.Type{decls.Bool, decls.Bool}, decls.Bool), + decls.NewOverload(overloads.LessInt64, + []*exprpb.Type{decls.Int, decls.Int}, decls.Bool), + decls.NewOverload(overloads.LessInt64Double, + []*exprpb.Type{decls.Int, decls.Double}, decls.Bool), + decls.NewOverload(overloads.LessInt64Uint64, + []*exprpb.Type{decls.Int, decls.Uint}, decls.Bool), + decls.NewOverload(overloads.LessUint64, + []*exprpb.Type{decls.Uint, decls.Uint}, decls.Bool), + decls.NewOverload(overloads.LessUint64Double, + []*exprpb.Type{decls.Uint, decls.Double}, decls.Bool), + decls.NewOverload(overloads.LessUint64Int64, + []*exprpb.Type{decls.Uint, decls.Int}, decls.Bool), + decls.NewOverload(overloads.LessDouble, + []*exprpb.Type{decls.Double, decls.Double}, decls.Bool), + decls.NewOverload(overloads.LessDoubleInt64, + []*exprpb.Type{decls.Double, decls.Int}, decls.Bool), + decls.NewOverload(overloads.LessDoubleUint64, + []*exprpb.Type{decls.Double, decls.Uint}, decls.Bool), + decls.NewOverload(overloads.LessString, + []*exprpb.Type{decls.String, decls.String}, decls.Bool), + decls.NewOverload(overloads.LessBytes, + []*exprpb.Type{decls.Bytes, decls.Bytes}, decls.Bool), + decls.NewOverload(overloads.LessTimestamp, + []*exprpb.Type{decls.Timestamp, decls.Timestamp}, decls.Bool), + decls.NewOverload(overloads.LessDuration, + []*exprpb.Type{decls.Duration, decls.Duration}, decls.Bool)), + + decls.NewFunction(operators.LessEquals, + decls.NewOverload(overloads.LessEqualsBool, + []*exprpb.Type{decls.Bool, decls.Bool}, decls.Bool), + decls.NewOverload(overloads.LessEqualsInt64, + []*exprpb.Type{decls.Int, decls.Int}, decls.Bool), + decls.NewOverload(overloads.LessEqualsInt64Double, + []*exprpb.Type{decls.Int, decls.Double}, decls.Bool), + decls.NewOverload(overloads.LessEqualsInt64Uint64, + []*exprpb.Type{decls.Int, decls.Uint}, decls.Bool), + decls.NewOverload(overloads.LessEqualsUint64, + []*exprpb.Type{decls.Uint, decls.Uint}, decls.Bool), + decls.NewOverload(overloads.LessEqualsUint64Double, + []*exprpb.Type{decls.Uint, decls.Double}, decls.Bool), + decls.NewOverload(overloads.LessEqualsUint64Int64, + []*exprpb.Type{decls.Uint, decls.Int}, decls.Bool), + decls.NewOverload(overloads.LessEqualsDouble, + []*exprpb.Type{decls.Double, decls.Double}, decls.Bool), + decls.NewOverload(overloads.LessEqualsDoubleInt64, + []*exprpb.Type{decls.Double, decls.Int}, decls.Bool), + decls.NewOverload(overloads.LessEqualsDoubleUint64, + []*exprpb.Type{decls.Double, decls.Uint}, decls.Bool), + decls.NewOverload(overloads.LessEqualsString, + []*exprpb.Type{decls.String, decls.String}, decls.Bool), + decls.NewOverload(overloads.LessEqualsBytes, + []*exprpb.Type{decls.Bytes, decls.Bytes}, decls.Bool), + decls.NewOverload(overloads.LessEqualsTimestamp, + []*exprpb.Type{decls.Timestamp, decls.Timestamp}, decls.Bool), + decls.NewOverload(overloads.LessEqualsDuration, + []*exprpb.Type{decls.Duration, decls.Duration}, decls.Bool)), + + decls.NewFunction(operators.Greater, + decls.NewOverload(overloads.GreaterBool, + []*exprpb.Type{decls.Bool, decls.Bool}, decls.Bool), + decls.NewOverload(overloads.GreaterInt64, + []*exprpb.Type{decls.Int, decls.Int}, decls.Bool), + decls.NewOverload(overloads.GreaterInt64Double, + []*exprpb.Type{decls.Int, decls.Double}, decls.Bool), + decls.NewOverload(overloads.GreaterInt64Uint64, + []*exprpb.Type{decls.Int, decls.Uint}, decls.Bool), + decls.NewOverload(overloads.GreaterUint64, + []*exprpb.Type{decls.Uint, decls.Uint}, decls.Bool), + decls.NewOverload(overloads.GreaterUint64Double, + []*exprpb.Type{decls.Uint, decls.Double}, decls.Bool), + decls.NewOverload(overloads.GreaterUint64Int64, + []*exprpb.Type{decls.Uint, decls.Int}, decls.Bool), + decls.NewOverload(overloads.GreaterDouble, + []*exprpb.Type{decls.Double, decls.Double}, decls.Bool), + decls.NewOverload(overloads.GreaterDoubleInt64, + []*exprpb.Type{decls.Double, decls.Int}, decls.Bool), + decls.NewOverload(overloads.GreaterDoubleUint64, + []*exprpb.Type{decls.Double, decls.Uint}, decls.Bool), + decls.NewOverload(overloads.GreaterString, + []*exprpb.Type{decls.String, decls.String}, decls.Bool), + decls.NewOverload(overloads.GreaterBytes, + []*exprpb.Type{decls.Bytes, decls.Bytes}, decls.Bool), + decls.NewOverload(overloads.GreaterTimestamp, + []*exprpb.Type{decls.Timestamp, decls.Timestamp}, decls.Bool), + decls.NewOverload(overloads.GreaterDuration, + []*exprpb.Type{decls.Duration, decls.Duration}, decls.Bool)), + + decls.NewFunction(operators.GreaterEquals, + decls.NewOverload(overloads.GreaterEqualsBool, + []*exprpb.Type{decls.Bool, decls.Bool}, decls.Bool), + decls.NewOverload(overloads.GreaterEqualsInt64, + []*exprpb.Type{decls.Int, decls.Int}, decls.Bool), + decls.NewOverload(overloads.GreaterEqualsInt64Double, + []*exprpb.Type{decls.Int, decls.Double}, decls.Bool), + decls.NewOverload(overloads.GreaterEqualsInt64Uint64, + []*exprpb.Type{decls.Int, decls.Uint}, decls.Bool), + decls.NewOverload(overloads.GreaterEqualsUint64, + []*exprpb.Type{decls.Uint, decls.Uint}, decls.Bool), + decls.NewOverload(overloads.GreaterEqualsUint64Double, + []*exprpb.Type{decls.Uint, decls.Double}, decls.Bool), + decls.NewOverload(overloads.GreaterEqualsUint64Int64, + []*exprpb.Type{decls.Uint, decls.Int}, decls.Bool), + decls.NewOverload(overloads.GreaterEqualsDouble, + []*exprpb.Type{decls.Double, decls.Double}, decls.Bool), + decls.NewOverload(overloads.GreaterEqualsDoubleInt64, + []*exprpb.Type{decls.Double, decls.Int}, decls.Bool), + decls.NewOverload(overloads.GreaterEqualsDoubleUint64, + []*exprpb.Type{decls.Double, decls.Uint}, decls.Bool), + decls.NewOverload(overloads.GreaterEqualsString, + []*exprpb.Type{decls.String, decls.String}, decls.Bool), + decls.NewOverload(overloads.GreaterEqualsBytes, + []*exprpb.Type{decls.Bytes, decls.Bytes}, decls.Bool), + decls.NewOverload(overloads.GreaterEqualsTimestamp, + []*exprpb.Type{decls.Timestamp, decls.Timestamp}, decls.Bool), + decls.NewOverload(overloads.GreaterEqualsDuration, + []*exprpb.Type{decls.Duration, decls.Duration}, decls.Bool)), + }...) +} + +// StandardDeclarations returns the Decls for all functions and constants in the evaluator. +func StandardDeclarations() []*exprpb.Decl { + return standardDeclarations } diff --git a/vendor/github.com/google/cel-go/checker/types.go b/vendor/github.com/google/cel-go/checker/types.go index 05d30aa1b..2962d5345 100644 --- a/vendor/github.com/google/cel-go/checker/types.go +++ b/vendor/github.com/google/cel-go/checker/types.go @@ -34,7 +34,7 @@ const ( kindWellKnown kindWrapper kindNull - kindAbstract // TODO: Update the checker protos to include abstract + kindAbstract kindType kindList kindMap @@ -149,21 +149,6 @@ func isEqualOrLessSpecific(t1 *exprpb.Type, t2 *exprpb.Type) bool { } } return true - case kindFunction: - fn1 := t1.GetFunction() - fn2 := t2.GetFunction() - if len(fn1.ArgTypes) != len(fn2.ArgTypes) { - return false - } - if !isEqualOrLessSpecific(fn1.ResultType, fn2.ResultType) { - return false - } - for i, a1 := range fn1.ArgTypes { - if !isEqualOrLessSpecific(a1, fn2.ArgTypes[i]) { - return false - } - } - return true case kindList: return isEqualOrLessSpecific(t1.GetListType().ElemType, t2.GetListType().ElemType) case kindMap: @@ -180,43 +165,26 @@ func isEqualOrLessSpecific(t1 *exprpb.Type, t2 *exprpb.Type) bool { /// internalIsAssignable returns true if t1 is assignable to t2. func internalIsAssignable(m *mapping, t1 *exprpb.Type, t2 *exprpb.Type) bool { - // A type is always assignable to itself. - // Early terminate the call to avoid cases of infinite recursion. - if proto.Equal(t1, t2) { - return true - } // Process type parameters. kind1, kind2 := kindOf(t1), kindOf(t2) if kind2 == kindTypeParam { - if t2Sub, found := m.find(t2); found { - // If the types are compatible, pick the more general type and return true - if internalIsAssignable(m, t1, t2Sub) { - m.add(t2, mostGeneral(t1, t2Sub)) - return true - } - return false - } - if notReferencedIn(m, t2, t1) { - m.add(t2, t1) + // If t2 is a valid type substitution for t1, return true. + valid, t2HasSub := isValidTypeSubstitution(m, t1, t2) + if valid { return true } + // If t2 is not a valid type sub for t1, and already has a known substitution return false + // since it is not possible for t1 to be a substitution for t2. + if !valid && t2HasSub { + return false + } + // Otherwise, fall through to check whether t1 is a possible substitution for t2. } if kind1 == kindTypeParam { - // For the lower type bound, we currently do not perform adjustment. The restricted - // way we use type parameters in lower type bounds, it is not necessary, but may - // become if we generalize type unification. - if t1Sub, found := m.find(t1); found { - // If the types are compatible, pick the more general type and return true - if internalIsAssignable(m, t1Sub, t2) { - m.add(t1, mostGeneral(t1Sub, t2)) - return true - } - return false - } - if notReferencedIn(m, t1, t2) { - m.add(t1, t2) - return true - } + // Return whether t1 is a valid substitution for t2. If not, do no additional checks as the + // possible type substitutions have been searched in both directions. + valid, _ := isValidTypeSubstitution(m, t2, t1) + return valid } // Next check for wildcard types. @@ -242,15 +210,11 @@ func internalIsAssignable(m *mapping, t1 *exprpb.Type, t2 *exprpb.Type) bool { switch kind1 { // ERROR, TYPE_PARAM, and DYN handled above. case kindAbstract: - return internalIsAssignableAbstractType(m, - t1.GetAbstractType(), t2.GetAbstractType()) + return internalIsAssignableAbstractType(m, t1.GetAbstractType(), t2.GetAbstractType()) case kindFunction: - return internalIsAssignableFunction(m, - t1.GetFunction(), t2.GetFunction()) + return internalIsAssignableFunction(m, t1.GetFunction(), t2.GetFunction()) case kindList: - return internalIsAssignable(m, - t1.GetListType().GetElemType(), - t2.GetListType().GetElemType()) + return internalIsAssignable(m, t1.GetListType().GetElemType(), t2.GetListType().GetElemType()) case kindMap: return internalIsAssignableMap(m, t1.GetMapType(), t2.GetMapType()) case kindObject: @@ -266,18 +230,40 @@ func internalIsAssignable(m *mapping, t1 *exprpb.Type, t2 *exprpb.Type) bool { } } +// isValidTypeSubstitution returns whether t2 (or its type substitution) is a valid type +// substitution for t1, and whether t2 has a type substitution in mapping m. +// +// The type t2 is a valid substitution for t1 if any of the following statements is true +// - t2 has a type substitition (t2sub) equal to t1 +// - t2 has a type substitution (t2sub) assignable to t1 +// - t2 does not occur within t1. +func isValidTypeSubstitution(m *mapping, t1, t2 *exprpb.Type) (valid, hasSub bool) { + if t2Sub, found := m.find(t2); found { + kind1, kind2 := kindOf(t1), kindOf(t2) + if kind1 == kind2 && proto.Equal(t1, t2Sub) { + return true, true + } + // If the types are compatible, pick the more general type and return true + if internalIsAssignable(m, t1, t2Sub) { + m.add(t2, mostGeneral(t1, t2Sub)) + return true, true + } + return false, true + } + if notReferencedIn(m, t2, t1) { + m.add(t2, t1) + return true, false + } + return false, false +} + // internalIsAssignableAbstractType returns true if the abstract type names agree and all type // parameters are assignable. func internalIsAssignableAbstractType(m *mapping, a1 *exprpb.Type_AbstractType, a2 *exprpb.Type_AbstractType) bool { - if a1.GetName() != a2.GetName() { - return false - } - if internalIsAssignableList(m, a1.GetParameterTypes(), a2.GetParameterTypes()) { - return true - } - return false + return a1.GetName() == a2.GetName() && + internalIsAssignableList(m, a1.GetParameterTypes(), a2.GetParameterTypes()) } // internalIsAssignableFunction returns true if the function return type and arg types are @@ -389,6 +375,8 @@ func kindOf(t *exprpb.Type) int { return kindObject case *exprpb.Type_TypeParam: return kindTypeParam + case *exprpb.Type_AbstractType_: + return kindAbstract } return kindUnknown } @@ -423,15 +411,6 @@ func notReferencedIn(m *mapping, t *exprpb.Type, withinType *exprpb.Type) bool { } } return true - case kindFunction: - fn := withinType.GetFunction() - types := flattenFunctionTypes(fn) - for _, a := range types { - if !notReferencedIn(m, t, a) { - return false - } - } - return true case kindList: return notReferencedIn(m, t, withinType.GetListType().ElemType) case kindMap: @@ -456,7 +435,6 @@ func substitute(m *mapping, t *exprpb.Type, typeParamToDyn bool) *exprpb.Type { } switch kind { case kindAbstract: - // TODO: implement! at := t.GetAbstractType() params := make([]*exprpb.Type, len(at.GetParameterTypes())) for i, p := range at.GetParameterTypes() { diff --git a/vendor/github.com/google/cel-go/common/cost.go b/vendor/github.com/google/cel-go/common/cost.go new file mode 100644 index 000000000..5e24bd0f4 --- /dev/null +++ b/vendor/github.com/google/cel-go/common/cost.go @@ -0,0 +1,40 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +const ( + // SelectAndIdentCost is the cost of an operation that accesses an identifier or performs a select. + SelectAndIdentCost = 1 + + // ConstCost is the cost of an operation that accesses a constant. + ConstCost = 0 + + // ListCreateBaseCost is the base cost of any operation that creates a new list. + ListCreateBaseCost = 10 + + // MapCreateBaseCost is the base cost of any operation that creates a new map. + MapCreateBaseCost = 30 + + // StructCreateBaseCost is the base cost of any operation that creates a new struct. + StructCreateBaseCost = 40 + + // StringTraversalCostFactor is multiplied to a length of a string when computing the cost of traversing the entire + // string once. + StringTraversalCostFactor = 0.1 + + // RegexStringLengthCostFactor is multiplied ot the length of a regex string pattern when computing the cost of + // applying the regex to a string of unit cost. + RegexStringLengthCostFactor = 0.25 +) diff --git a/vendor/github.com/google/cel-go/common/location.go b/vendor/github.com/google/cel-go/common/location.go index 31fce6cd3..ec3fa7cb5 100644 --- a/vendor/github.com/google/cel-go/common/location.go +++ b/vendor/github.com/google/cel-go/common/location.go @@ -27,7 +27,7 @@ type SourceLocation struct { } var ( - // Location implements the SourcceLocation interface. + // Location implements the SourceLocation interface. _ Location = &SourceLocation{} // NoLocation is a particular illegal location. NoLocation = &SourceLocation{-1, -1} diff --git a/vendor/github.com/google/cel-go/common/operators/operators.go b/vendor/github.com/google/cel-go/common/operators/operators.go index 8f832c4d4..8a2e90945 100644 --- a/vendor/github.com/google/cel-go/common/operators/operators.go +++ b/vendor/github.com/google/cel-go/common/operators/operators.go @@ -14,7 +14,7 @@ // Package operators defines the internal function names of operators. // -// ALl operators in the expression language are modelled as function calls. +// All operators in the expression language are modelled as function calls. package operators // String "names" for CEL operators. @@ -70,46 +70,35 @@ var ( "!=": NotEquals, "-": Subtract, } - reverseOperators = map[string]string{ - Add: "+", - Divide: "/", - Equals: "==", - Greater: ">", - GreaterEquals: ">=", - In: "in", - Less: "<", - LessEquals: "<=", - LogicalAnd: "&&", - LogicalNot: "!", - LogicalOr: "||", - Modulo: "%", - Multiply: "*", - Negate: "-", - NotEquals: "!=", - OldIn: "in", - Subtract: "-", - } - // precedence of the operator, where the higher value means higher. - precedence = map[string]int{ - Conditional: 8, - LogicalOr: 7, - LogicalAnd: 6, - Equals: 5, - Greater: 5, - GreaterEquals: 5, - In: 5, - Less: 5, - LessEquals: 5, - NotEquals: 5, - OldIn: 5, - Add: 4, - Subtract: 4, - Divide: 3, - Modulo: 3, - Multiply: 3, - LogicalNot: 2, - Negate: 2, - Index: 1, + // operatorMap of the operator symbol which refers to a struct containing the display name, + // if applicable, the operator precedence, and the arity. + // + // If the symbol does not have a display name listed in the map, it is only because it requires + // special casing to render properly as text. + operatorMap = map[string]struct { + displayName string + precedence int + arity int + }{ + Conditional: {displayName: "", precedence: 8, arity: 3}, + LogicalOr: {displayName: "||", precedence: 7, arity: 2}, + LogicalAnd: {displayName: "&&", precedence: 6, arity: 2}, + Equals: {displayName: "==", precedence: 5, arity: 2}, + Greater: {displayName: ">", precedence: 5, arity: 2}, + GreaterEquals: {displayName: ">=", precedence: 5, arity: 2}, + In: {displayName: "in", precedence: 5, arity: 2}, + Less: {displayName: "<", precedence: 5, arity: 2}, + LessEquals: {displayName: "<=", precedence: 5, arity: 2}, + NotEquals: {displayName: "!=", precedence: 5, arity: 2}, + OldIn: {displayName: "in", precedence: 5, arity: 2}, + Add: {displayName: "+", precedence: 4, arity: 2}, + Subtract: {displayName: "-", precedence: 4, arity: 2}, + Divide: {displayName: "/", precedence: 3, arity: 2}, + Modulo: {displayName: "%", precedence: 3, arity: 2}, + Multiply: {displayName: "*", precedence: 3, arity: 2}, + LogicalNot: {displayName: "!", precedence: 2, arity: 1}, + Negate: {displayName: "-", precedence: 2, arity: 1}, + Index: {displayName: "", precedence: 1, arity: 2}, } ) @@ -120,26 +109,35 @@ func Find(text string) (string, bool) { } // FindReverse returns the unmangled, text representation of the operator. -func FindReverse(op string) (string, bool) { - txt, found := reverseOperators[op] - return txt, found +func FindReverse(symbol string) (string, bool) { + op, found := operatorMap[symbol] + if !found { + return "", false + } + return op.displayName, true } // FindReverseBinaryOperator returns the unmangled, text representation of a binary operator. -func FindReverseBinaryOperator(op string) (string, bool) { - if op == LogicalNot || op == Negate { +// +// If the symbol does refer to an operator, but the operator does not have a display name the +// result is false. +func FindReverseBinaryOperator(symbol string) (string, bool) { + op, found := operatorMap[symbol] + if !found || op.arity != 2 { return "", false } - txt, found := reverseOperators[op] - return txt, found + if op.displayName == "" { + return "", false + } + return op.displayName, true } // Precedence returns the operator precedence, where the higher the number indicates // higher precedence operations. -func Precedence(op string) int { - p, found := precedence[op] - if found { - return p +func Precedence(symbol string) int { + op, found := operatorMap[symbol] + if !found { + return 0 } - return 0 + return op.precedence } diff --git a/vendor/github.com/google/cel-go/common/overloads/overloads.go b/vendor/github.com/google/cel-go/common/overloads/overloads.go index a1c01ee72..9ebaf6fab 100644 --- a/vendor/github.com/google/cel-go/common/overloads/overloads.go +++ b/vendor/github.com/google/cel-go/common/overloads/overloads.go @@ -18,45 +18,69 @@ package overloads // Boolean logic overloads const ( - Conditional = "conditional" - LogicalAnd = "logical_and" - LogicalOr = "logical_or" - LogicalNot = "logical_not" - NotStrictlyFalse = "not_strictly_false" - Equals = "equals" - NotEquals = "not_equals" - LessBool = "less_bool" - LessInt64 = "less_int64" - LessUint64 = "less_uint64" - LessDouble = "less_double" - LessString = "less_string" - LessBytes = "less_bytes" - LessTimestamp = "less_timestamp" - LessDuration = "less_duration" - LessEqualsBool = "less_equals_bool" - LessEqualsInt64 = "less_equals_int64" - LessEqualsUint64 = "less_equals_uint64" - LessEqualsDouble = "less_equals_double" - LessEqualsString = "less_equals_string" - LessEqualsBytes = "less_equals_bytes" - LessEqualsTimestamp = "less_equals_timestamp" - LessEqualsDuration = "less_equals_duration" - GreaterBool = "greater_bool" - GreaterInt64 = "greater_int64" - GreaterUint64 = "greater_uint64" - GreaterDouble = "greater_double" - GreaterString = "greater_string" - GreaterBytes = "greater_bytes" - GreaterTimestamp = "greater_timestamp" - GreaterDuration = "greater_duration" - GreaterEqualsBool = "greater_equals_bool" - GreaterEqualsInt64 = "greater_equals_int64" - GreaterEqualsUint64 = "greater_equals_uint64" - GreaterEqualsDouble = "greater_equals_double" - GreaterEqualsString = "greater_equals_string" - GreaterEqualsBytes = "greater_equals_bytes" - GreaterEqualsTimestamp = "greater_equals_timestamp" - GreaterEqualsDuration = "greater_equals_duration" + Conditional = "conditional" + LogicalAnd = "logical_and" + LogicalOr = "logical_or" + LogicalNot = "logical_not" + NotStrictlyFalse = "not_strictly_false" + Equals = "equals" + NotEquals = "not_equals" + LessBool = "less_bool" + LessInt64 = "less_int64" + LessInt64Double = "less_int64_double" + LessInt64Uint64 = "less_int64_uint64" + LessUint64 = "less_uint64" + LessUint64Double = "less_uint64_double" + LessUint64Int64 = "less_uint64_int64" + LessDouble = "less_double" + LessDoubleInt64 = "less_double_int64" + LessDoubleUint64 = "less_double_uint64" + LessString = "less_string" + LessBytes = "less_bytes" + LessTimestamp = "less_timestamp" + LessDuration = "less_duration" + LessEqualsBool = "less_equals_bool" + LessEqualsInt64 = "less_equals_int64" + LessEqualsInt64Double = "less_equals_int64_double" + LessEqualsInt64Uint64 = "less_equals_int64_uint64" + LessEqualsUint64 = "less_equals_uint64" + LessEqualsUint64Double = "less_equals_uint64_double" + LessEqualsUint64Int64 = "less_equals_uint64_int64" + LessEqualsDouble = "less_equals_double" + LessEqualsDoubleInt64 = "less_equals_double_int64" + LessEqualsDoubleUint64 = "less_equals_double_uint64" + LessEqualsString = "less_equals_string" + LessEqualsBytes = "less_equals_bytes" + LessEqualsTimestamp = "less_equals_timestamp" + LessEqualsDuration = "less_equals_duration" + GreaterBool = "greater_bool" + GreaterInt64 = "greater_int64" + GreaterInt64Double = "greater_int64_double" + GreaterInt64Uint64 = "greater_int64_uint64" + GreaterUint64 = "greater_uint64" + GreaterUint64Double = "greater_uint64_double" + GreaterUint64Int64 = "greater_uint64_int64" + GreaterDouble = "greater_double" + GreaterDoubleInt64 = "greater_double_int64" + GreaterDoubleUint64 = "greater_double_uint64" + GreaterString = "greater_string" + GreaterBytes = "greater_bytes" + GreaterTimestamp = "greater_timestamp" + GreaterDuration = "greater_duration" + GreaterEqualsBool = "greater_equals_bool" + GreaterEqualsInt64 = "greater_equals_int64" + GreaterEqualsInt64Double = "greater_equals_int64_double" + GreaterEqualsInt64Uint64 = "greater_equals_int64_uint64" + GreaterEqualsUint64 = "greater_equals_uint64" + GreaterEqualsUint64Double = "greater_equals_uint64_double" + GreaterEqualsUint64Int64 = "greater_equals_uint64_int64" + GreaterEqualsDouble = "greater_equals_double" + GreaterEqualsDoubleInt64 = "greater_equals_double_int64" + GreaterEqualsDoubleUint64 = "greater_equals_double_uint64" + GreaterEqualsString = "greater_equals_string" + GreaterEqualsBytes = "greater_equals_bytes" + GreaterEqualsTimestamp = "greater_equals_timestamp" + GreaterEqualsDuration = "greater_equals_duration" ) // Math overloads diff --git a/vendor/github.com/google/cel-go/common/runes/buffer.go b/vendor/github.com/google/cel-go/common/runes/buffer.go new file mode 100644 index 000000000..50aac0b27 --- /dev/null +++ b/vendor/github.com/google/cel-go/common/runes/buffer.go @@ -0,0 +1,194 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package runes provides interfaces and utilities for working with runes. +package runes + +import ( + "strings" + "unicode/utf8" +) + +// Buffer is an interface for accessing a contiguous array of code points. +type Buffer interface { + Get(i int) rune + Slice(i, j int) string + Len() int +} + +type emptyBuffer struct{} + +func (e *emptyBuffer) Get(i int) rune { + panic("slice index out of bounds") +} + +func (e *emptyBuffer) Slice(i, j int) string { + if i != 0 || i != j { + panic("slice index out of bounds") + } + return "" +} + +func (e *emptyBuffer) Len() int { + return 0 +} + +var _ Buffer = &emptyBuffer{} + +// asciiBuffer is an implementation for an array of code points that contain code points only from +// the ASCII character set. +type asciiBuffer struct { + arr []byte +} + +func (a *asciiBuffer) Get(i int) rune { + return rune(uint32(a.arr[i])) +} + +func (a *asciiBuffer) Slice(i, j int) string { + return string(a.arr[i:j]) +} + +func (a *asciiBuffer) Len() int { + return len(a.arr) +} + +var _ Buffer = &asciiBuffer{} + +// basicBuffer is an implementation for an array of code points that contain code points from both +// the Latin-1 character set and Basic Multilingual Plane. +type basicBuffer struct { + arr []uint16 +} + +func (b *basicBuffer) Get(i int) rune { + return rune(uint32(b.arr[i])) +} + +func (b *basicBuffer) Slice(i, j int) string { + var str strings.Builder + str.Grow((j - i) * 3) // Worst case encoding size for 0xffff is 3. + for ; i < j; i++ { + str.WriteRune(rune(uint32(b.arr[i]))) + } + return str.String() +} + +func (b *basicBuffer) Len() int { + return len(b.arr) +} + +var _ Buffer = &basicBuffer{} + +// supplementalBuffer is an implementation for an array of code points that contain code points from +// the Latin-1 character set, Basic Multilingual Plane, or the Supplemental Multilingual Plane. +type supplementalBuffer struct { + arr []rune +} + +func (s *supplementalBuffer) Get(i int) rune { + return rune(uint32(s.arr[i])) +} + +func (s *supplementalBuffer) Slice(i, j int) string { + return string(s.arr[i:j]) +} + +func (s *supplementalBuffer) Len() int { + return len(s.arr) +} + +var _ Buffer = &supplementalBuffer{} + +var nilBuffer = &emptyBuffer{} + +// NewBuffer returns an efficient implementation of Buffer for the given text based on the ranges of +// the encoded code points contained within. +// +// Code points are represented as an array of byte, uint16, or rune. This approach ensures that +// each index represents a code point by itself without needing to use an array of rune. At first +// we assume all code points are less than or equal to '\u007f'. If this holds true, the +// underlying storage is a byte array containing only ASCII characters. If we encountered a code +// point above this range but less than or equal to '\uffff' we allocate a uint16 array, copy the +// elements of previous byte array to the uint16 array, and continue. If this holds true, the +// underlying storage is a uint16 array containing only Unicode characters in the Basic Multilingual +// Plane. If we encounter a code point above '\uffff' we allocate an rune array, copy the previous +// elements of the byte or uint16 array, and continue. The underlying storage is an rune array +// containing any Unicode character. +func NewBuffer(data string) Buffer { + if len(data) == 0 { + return nilBuffer + } + var ( + idx = 0 + buf8 = make([]byte, 0, len(data)) + buf16 []uint16 + buf32 []rune + ) + for idx < len(data) { + r, s := utf8.DecodeRuneInString(data[idx:]) + idx += s + if r < utf8.RuneSelf { + buf8 = append(buf8, byte(r)) + continue + } + if r <= 0xffff { + buf16 = make([]uint16, len(buf8), len(data)) + for i, v := range buf8 { + buf16[i] = uint16(v) + } + buf8 = nil + buf16 = append(buf16, uint16(r)) + goto copy16 + } + buf32 = make([]rune, len(buf8), len(data)) + for i, v := range buf8 { + buf32[i] = rune(uint32(v)) + } + buf8 = nil + buf32 = append(buf32, r) + goto copy32 + } + return &asciiBuffer{ + arr: buf8, + } +copy16: + for idx < len(data) { + r, s := utf8.DecodeRuneInString(data[idx:]) + idx += s + if r <= 0xffff { + buf16 = append(buf16, uint16(r)) + continue + } + buf32 = make([]rune, len(buf16), len(data)) + for i, v := range buf16 { + buf32[i] = rune(uint32(v)) + } + buf16 = nil + buf32 = append(buf32, r) + goto copy32 + } + return &basicBuffer{ + arr: buf16, + } +copy32: + for idx < len(data) { + r, s := utf8.DecodeRuneInString(data[idx:]) + idx += s + buf32 = append(buf32, r) + } + return &supplementalBuffer{ + arr: buf32, + } +} diff --git a/vendor/github.com/google/cel-go/common/source.go b/vendor/github.com/google/cel-go/common/source.go index d4fa4bbfc..52377d930 100644 --- a/vendor/github.com/google/cel-go/common/source.go +++ b/vendor/github.com/google/cel-go/common/source.go @@ -18,6 +18,8 @@ import ( "strings" "unicode/utf8" + "github.com/google/cel-go/common/runes" + exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" ) @@ -59,12 +61,14 @@ type Source interface { // The sourceImpl type implementation of the Source interface. type sourceImpl struct { - contents []rune + runes.Buffer description string lineOffsets []int32 idOffsets map[int64]int32 } +var _ runes.Buffer = &sourceImpl{} + // TODO(jimlarson) "Character offsets" should index the code points // within the UTF-8 encoded string. It currently indexes bytes. // Can be accomplished by using rune[] instead of string for contents. @@ -85,7 +89,7 @@ func NewStringSource(contents string, description string) Source { offsets[int32(i)] = offset } return &sourceImpl{ - contents: []rune(contents), + Buffer: runes.NewBuffer(contents), description: description, lineOffsets: offsets, idOffsets: map[int64]int32{}, @@ -95,16 +99,16 @@ func NewStringSource(contents string, description string) Source { // NewInfoSource creates a new Source from a SourceInfo. func NewInfoSource(info *exprpb.SourceInfo) Source { return &sourceImpl{ - contents: []rune(""), - description: info.Location, - lineOffsets: info.LineOffsets, - idOffsets: info.Positions, + Buffer: runes.NewBuffer(""), + description: info.GetLocation(), + lineOffsets: info.GetLineOffsets(), + idOffsets: info.GetPositions(), } } // Content implements the Source interface method. func (s *sourceImpl) Content() string { - return string(s.contents) + return s.Slice(0, s.Len()) } // Description implements the Source interface method. @@ -139,14 +143,14 @@ func (s *sourceImpl) OffsetLocation(offset int32) (Location, bool) { // Snippet implements the Source interface method. func (s *sourceImpl) Snippet(line int) (string, bool) { charStart, found := s.findLineOffset(line) - if !found || len(s.contents) == 0 { + if !found || s.Len() == 0 { return "", false } charEnd, found := s.findLineOffset(line + 1) if found { - return string(s.contents[charStart : charEnd-1]), true + return s.Slice(int(charStart), int(charEnd-1)), true } - return string(s.contents[charStart:]), true + return s.Slice(int(charStart), s.Len()), true } // findLineOffset returns the offset where the (1-indexed) line begins, diff --git a/vendor/github.com/google/cel-go/common/types/bool.go b/vendor/github.com/google/cel-go/common/types/bool.go index 16214c257..749cc2485 100644 --- a/vendor/github.com/google/cel-go/common/types/bool.go +++ b/vendor/github.com/google/cel-go/common/types/bool.go @@ -41,7 +41,7 @@ var ( ) // Boolean constants -var ( +const ( False = Bool(false) True = Bool(true) ) @@ -111,10 +111,7 @@ func (b Bool) ConvertToType(typeVal ref.Type) ref.Val { // Equal implements the ref.Val interface method. func (b Bool) Equal(other ref.Val) ref.Val { otherBool, ok := other.(Bool) - if !ok { - return ValOrErr(other, "no such overload") - } - return Bool(b == otherBool) + return Bool(ok && b == otherBool) } // Negate implements the traits.Negater interface method. @@ -133,12 +130,11 @@ func (b Bool) Value() interface{} { } // IsBool returns whether the input ref.Val or ref.Type is equal to BoolType. -func IsBool(elem interface{}) bool { - switch elem := elem.(type) { - case ref.Type: - return elem == BoolType - case ref.Val: - return IsBool(elem.Type()) +func IsBool(elem ref.Val) bool { + switch elem.(type) { + case Bool: + return true + default: + return false } - return false } diff --git a/vendor/github.com/google/cel-go/common/types/bytes.go b/vendor/github.com/google/cel-go/common/types/bytes.go index 5ef367f02..3575717ec 100644 --- a/vendor/github.com/google/cel-go/common/types/bytes.go +++ b/vendor/github.com/google/cel-go/common/types/bytes.go @@ -53,7 +53,7 @@ func (b Bytes) Add(other ref.Val) ref.Val { return append(b, otherBytes...) } -// Compare implments traits.Comparer interface method by lexicographic ordering. +// Compare implements traits.Comparer interface method by lexicographic ordering. func (b Bytes) Compare(other ref.Val) ref.Val { otherBytes, ok := other.(Bytes) if !ok { @@ -113,10 +113,7 @@ func (b Bytes) ConvertToType(typeVal ref.Type) ref.Val { // Equal implements the ref.Val interface method. func (b Bytes) Equal(other ref.Val) ref.Val { otherBytes, ok := other.(Bytes) - if !ok { - return ValOrErr(other, "no such overload") - } - return Bool(bytes.Equal(b, otherBytes)) + return Bool(ok && bytes.Equal(b, otherBytes)) } // Size implements the traits.Sizer interface method. diff --git a/vendor/github.com/google/cel-go/common/types/compare.go b/vendor/github.com/google/cel-go/common/types/compare.go new file mode 100644 index 000000000..e19682618 --- /dev/null +++ b/vendor/github.com/google/cel-go/common/types/compare.go @@ -0,0 +1,97 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "math" + + "github.com/google/cel-go/common/types/ref" +) + +func compareDoubleInt(d Double, i Int) Int { + if d < math.MinInt64 { + return IntNegOne + } + if d > math.MaxInt64 { + return IntOne + } + return compareDouble(d, Double(i)) +} + +func compareIntDouble(i Int, d Double) Int { + return -compareDoubleInt(d, i) +} + +func compareDoubleUint(d Double, u Uint) Int { + if d < 0 { + return IntNegOne + } + if d > math.MaxUint64 { + return IntOne + } + return compareDouble(d, Double(u)) +} + +func compareUintDouble(u Uint, d Double) Int { + return -compareDoubleUint(d, u) +} + +func compareIntUint(i Int, u Uint) Int { + if i < 0 || u > math.MaxInt64 { + return IntNegOne + } + cmp := i - Int(u) + if cmp < 0 { + return IntNegOne + } + if cmp > 0 { + return IntOne + } + return IntZero +} + +func compareUintInt(u Uint, i Int) Int { + return -compareIntUint(i, u) +} + +func compareDouble(a, b Double) Int { + if a < b { + return IntNegOne + } + if a > b { + return IntOne + } + return IntZero +} + +func compareInt(a, b Int) ref.Val { + if a < b { + return IntNegOne + } + if a > b { + return IntOne + } + return IntZero +} + +func compareUint(a, b Uint) ref.Val { + if a < b { + return IntNegOne + } + if a > b { + return IntOne + } + return IntZero +} diff --git a/vendor/github.com/google/cel-go/common/types/double.go b/vendor/github.com/google/cel-go/common/types/double.go index 54c66faa6..a6ec52a0f 100644 --- a/vendor/github.com/google/cel-go/common/types/double.go +++ b/vendor/github.com/google/cel-go/common/types/double.go @@ -52,24 +52,29 @@ var ( func (d Double) Add(other ref.Val) ref.Val { otherDouble, ok := other.(Double) if !ok { - return ValOrErr(other, "no such overload") + return MaybeNoSuchOverloadErr(other) } return d + otherDouble } // Compare implements traits.Comparer.Compare. func (d Double) Compare(other ref.Val) ref.Val { - otherDouble, ok := other.(Double) - if !ok { - return ValOrErr(other, "no such overload") + if math.IsNaN(float64(d)) { + return NewErr("NaN values cannot be ordered") } - if d < otherDouble { - return IntNegOne + switch ov := other.(type) { + case Double: + if math.IsNaN(float64(ov)) { + return NewErr("NaN values cannot be ordered") + } + return compareDouble(d, ov) + case Int: + return compareDoubleInt(d, ov) + case Uint: + return compareDoubleUint(d, ov) + default: + return MaybeNoSuchOverloadErr(other) } - if d > otherDouble { - return IntOne - } - return IntZero } // ConvertToNative implements ref.Val.ConvertToNative. @@ -127,17 +132,17 @@ func (d Double) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { func (d Double) ConvertToType(typeVal ref.Type) ref.Val { switch typeVal { case IntType: - i := math.Round(float64(d)) - if i > math.MaxInt64 || i < math.MinInt64 { - return NewErr("range error converting %g to int", float64(d)) + i, err := doubleToInt64Checked(float64(d)) + if err != nil { + return wrapErr(err) } - return Int(float64(i)) + return Int(i) case UintType: - i := math.Round(float64(d)) - if i > math.MaxUint64 || i < 0 { - return NewErr("range error converting %g to int", float64(d)) + i, err := doubleToUint64Checked(float64(d)) + if err != nil { + return wrapErr(err) } - return Uint(float64(i)) + return Uint(i) case DoubleType: return d case StringType: @@ -152,26 +157,36 @@ func (d Double) ConvertToType(typeVal ref.Type) ref.Val { func (d Double) Divide(other ref.Val) ref.Val { otherDouble, ok := other.(Double) if !ok { - return ValOrErr(other, "no such overload") + return MaybeNoSuchOverloadErr(other) } return d / otherDouble } // Equal implements ref.Val.Equal. func (d Double) Equal(other ref.Val) ref.Val { - otherDouble, ok := other.(Double) - if !ok { - return ValOrErr(other, "no such overload") + if math.IsNaN(float64(d)) { + return False + } + switch ov := other.(type) { + case Double: + if math.IsNaN(float64(ov)) { + return False + } + return Bool(d == ov) + case Int: + return Bool(compareDoubleInt(d, ov) == 0) + case Uint: + return Bool(compareDoubleUint(d, ov) == 0) + default: + return False } - // TODO: Handle NaNs properly. - return Bool(d == otherDouble) } // Multiply implements traits.Multiplier.Multiply. func (d Double) Multiply(other ref.Val) ref.Val { otherDouble, ok := other.(Double) if !ok { - return ValOrErr(other, "no such overload") + return MaybeNoSuchOverloadErr(other) } return d * otherDouble } @@ -185,7 +200,7 @@ func (d Double) Negate() ref.Val { func (d Double) Subtract(subtrahend ref.Val) ref.Val { subtraDouble, ok := subtrahend.(Double) if !ok { - return ValOrErr(subtrahend, "no such overload") + return MaybeNoSuchOverloadErr(subtrahend) } return d - subtraDouble } diff --git a/vendor/github.com/google/cel-go/common/types/duration.go b/vendor/github.com/google/cel-go/common/types/duration.go index 5a14b024e..418349fa6 100644 --- a/vendor/github.com/google/cel-go/common/types/duration.go +++ b/vendor/github.com/google/cel-go/common/types/duration.go @@ -36,6 +36,10 @@ type Duration struct { time.Duration } +func durationOf(d time.Duration) Duration { + return Duration{Duration: d} +} + var ( // DurationType singleton. DurationType = NewTypeValue("google.protobuf.Duration", @@ -51,28 +55,38 @@ func (d Duration) Add(other ref.Val) ref.Val { switch other.Type() { case DurationType: dur2 := other.(Duration) - return Duration{Duration: d.Duration + dur2.Duration} + val, err := addDurationChecked(d.Duration, dur2.Duration) + if err != nil { + return wrapErr(err) + } + return durationOf(val) case TimestampType: ts := other.(Timestamp).Time - return Timestamp{Time: ts.Add(d.Duration)} + val, err := addTimeDurationChecked(ts, d.Duration) + if err != nil { + return wrapErr(err) + } + return timestampOf(val) } - return ValOrErr(other, "no such overload") + return MaybeNoSuchOverloadErr(other) } // Compare implements traits.Comparer.Compare. func (d Duration) Compare(other ref.Val) ref.Val { otherDur, ok := other.(Duration) if !ok { - return ValOrErr(other, "no such overload") + return MaybeNoSuchOverloadErr(other) } - dur := d.Duration - otherDur.Duration - if dur < 0 { + d1 := d.Duration + d2 := otherDur.Duration + switch { + case d1 < d2: return IntNegOne - } - if dur > 0 { + case d1 > d2: return IntOne + default: + return IntZero } - return IntZero } // ConvertToNative implements ref.Val.ConvertToNative. @@ -121,15 +135,16 @@ func (d Duration) ConvertToType(typeVal ref.Type) ref.Val { // Equal implements ref.Val.Equal. func (d Duration) Equal(other ref.Val) ref.Val { otherDur, ok := other.(Duration) - if !ok { - return ValOrErr(other, "no such overload") - } - return Bool(d.Duration == otherDur.Duration) + return Bool(ok && d.Duration == otherDur.Duration) } // Negate implements traits.Negater.Negate. func (d Duration) Negate() ref.Val { - return Duration{Duration: -d.Duration} + val, err := negateDurationChecked(d.Duration) + if err != nil { + return wrapErr(err) + } + return durationOf(val) } // Receive implements traits.Receiver.Receive. @@ -139,16 +154,20 @@ func (d Duration) Receive(function string, overload string, args []ref.Val) ref. return f(d.Duration) } } - return NewErr("no such overload") + return NoSuchOverloadErr() } // Subtract implements traits.Subtractor.Subtract. func (d Duration) Subtract(subtrahend ref.Val) ref.Val { subtraDur, ok := subtrahend.(Duration) if !ok { - return ValOrErr(subtrahend, "no such overload") + return MaybeNoSuchOverloadErr(subtrahend) } - return d.Add(subtraDur.Negate()) + val, err := subtractDurationChecked(d.Duration, subtraDur.Duration) + if err != nil { + return wrapErr(err) + } + return durationOf(val) } // Type implements ref.Val.Type. diff --git a/vendor/github.com/google/cel-go/common/types/err.go b/vendor/github.com/google/cel-go/common/types/err.go index 5cccb53d0..3fb87f507 100644 --- a/vendor/github.com/google/cel-go/common/types/err.go +++ b/vendor/github.com/google/cel-go/common/types/err.go @@ -15,6 +15,7 @@ package types import ( + "errors" "fmt" "reflect" @@ -29,6 +30,23 @@ type Err struct { var ( // ErrType singleton. ErrType = NewTypeValue("error") + + // errDivideByZero is an error indicating a division by zero of an integer value. + errDivideByZero = errors.New("division by zero") + // errModulusByZero is an error indicating a modulus by zero of an integer value. + errModulusByZero = errors.New("modulus by zero") + // errIntOverflow is an error representing integer overflow. + errIntOverflow = errors.New("integer overflow") + // errUintOverflow is an error representing unsigned integer overflow. + errUintOverflow = errors.New("unsigned integer overflow") + // errDurationOverflow is an error representing duration overflow. + errDurationOverflow = errors.New("duration overflow") + // errTimestampOverflow is an error representing timestamp overflow. + errTimestampOverflow = errors.New("timestamp overflow") + celErrTimestampOverflow = &Err{error: errTimestampOverflow} + + // celErrNoSuchOverload indicates that the call arguments did not match a supported method signature. + celErrNoSuchOverload = NewErr("no such overload") ) // NewErr creates a new Err described by the format string and args. @@ -39,7 +57,7 @@ func NewErr(format string, args ...interface{}) ref.Val { // NoSuchOverloadErr returns a new types.Err instance with a no such overload message. func NoSuchOverloadErr() ref.Val { - return NewErr("no such overload") + return celErrNoSuchOverload } // UnsupportedRefValConversionErr returns a types.NewErr instance with a no such conversion @@ -60,12 +78,15 @@ func ValOrErr(val ref.Val, format string, args ...interface{}) ref.Val { if val == nil { return NewErr(format, args...) } - switch val.Type() { - case ErrType, UnknownType: + if IsUnknownOrError(val) { return val - default: - return NewErr(format, args...) } + return NewErr(format, args...) +} + +// wrapErr wraps an existing Go error value into a CEL Err value. +func wrapErr(err error) ref.Val { + return &Err{error: err} } // ConvertToNative implements ref.Val.ConvertToNative. @@ -103,5 +124,10 @@ func (e *Err) Value() interface{} { // IsError returns whether the input element ref.Type or ref.Val is equal to // the ErrType singleton. func IsError(val ref.Val) bool { - return val.Type() == ErrType + switch val.(type) { + case *Err: + return true + default: + return false + } } diff --git a/vendor/github.com/google/cel-go/common/types/int.go b/vendor/github.com/google/cel-go/common/types/int.go index 4b76ce265..95f25dcd8 100644 --- a/vendor/github.com/google/cel-go/common/types/int.go +++ b/vendor/github.com/google/cel-go/common/types/int.go @@ -62,37 +62,46 @@ var ( func (i Int) Add(other ref.Val) ref.Val { otherInt, ok := other.(Int) if !ok { - return ValOrErr(other, "no such overload") + return MaybeNoSuchOverloadErr(other) } - if (otherInt > 0 && i > math.MaxInt64-otherInt) || (otherInt < 0 && i < math.MinInt64-otherInt) { - return NewErr("integer overflow") + val, err := addInt64Checked(int64(i), int64(otherInt)) + if err != nil { + return wrapErr(err) } - return i + otherInt + return Int(val) } // Compare implements traits.Comparer.Compare. func (i Int) Compare(other ref.Val) ref.Val { - otherInt, ok := other.(Int) - if !ok { - return ValOrErr(other, "no such overload") + switch ov := other.(type) { + case Double: + if math.IsNaN(float64(ov)) { + return NewErr("NaN values cannot be ordered") + } + return compareIntDouble(i, ov) + case Int: + return compareInt(i, ov) + case Uint: + return compareIntUint(i, ov) + default: + return MaybeNoSuchOverloadErr(other) } - if i < otherInt { - return IntNegOne - } - if i > otherInt { - return IntOne - } - return IntZero } // ConvertToNative implements ref.Val.ConvertToNative. func (i Int) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { switch typeDesc.Kind() { - case reflect.Int, reflect.Int32, reflect.Int64: + case reflect.Int, reflect.Int32: // Enums are also mapped as int32 derivations. // Note, the code doesn't convert to the enum value directly since this is not known, but // the net effect with respect to proto-assignment is handled correctly by the reflection // Convert method. + v, err := int64ToInt32Checked(int64(i)) + if err != nil { + return nil, err + } + return reflect.ValueOf(v).Convert(typeDesc).Interface(), nil + case reflect.Int64: return reflect.ValueOf(i).Convert(typeDesc).Interface(), nil case reflect.Ptr: switch typeDesc { @@ -100,8 +109,12 @@ func (i Int) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { // Primitives must be wrapped before being set on an Any field. return anypb.New(wrapperspb.Int64(int64(i))) case int32WrapperType: - // Convert the value to a wrapperspb.Int32Value (with truncation). - return wrapperspb.Int32(int32(i)), nil + // Convert the value to a wrapperspb.Int32Value, error on overflow. + v, err := int64ToInt32Checked(int64(i)) + if err != nil { + return nil, err + } + return wrapperspb.Int32(v), nil case int64WrapperType: // Convert the value to a wrapperspb.Int64Value. return wrapperspb.Int64(int64(i)), nil @@ -129,7 +142,11 @@ func (i Int) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { } switch typeDesc.Elem().Kind() { case reflect.Int32: - v := int32(i) + // Convert the value to a wrapperspb.Int32Value, error on overflow. + v, err := int64ToInt32Checked(int64(i)) + if err != nil { + return nil, err + } p := reflect.New(typeDesc.Elem()) p.Elem().Set(reflect.ValueOf(v).Convert(typeDesc.Elem())) return p.Interface(), nil @@ -157,17 +174,22 @@ func (i Int) ConvertToType(typeVal ref.Type) ref.Val { case IntType: return i case UintType: - if i < 0 { - return NewErr("range error converting %d to uint", i) + u, err := int64ToUint64Checked(int64(i)) + if err != nil { + return wrapErr(err) } - return Uint(i) + return Uint(u) case DoubleType: return Double(i) case StringType: return String(fmt.Sprintf("%d", int64(i))) case TimestampType: - t := time.Unix(int64(i), 0).UTC() - return Timestamp{Time: t} + // The maximum positive value that can be passed to time.Unix is math.MaxInt64 minus the number + // of seconds between year 1 and year 1970. See comments on unixToInternal. + if int64(i) < minUnixTime || int64(i) > maxUnixTime { + return celErrTimestampOverflow + } + return timestampOf(time.Unix(int64(i), 0).UTC()) case TypeType: return IntType } @@ -178,79 +200,78 @@ func (i Int) ConvertToType(typeVal ref.Type) ref.Val { func (i Int) Divide(other ref.Val) ref.Val { otherInt, ok := other.(Int) if !ok { - return ValOrErr(other, "no such overload") + return MaybeNoSuchOverloadErr(other) } - if otherInt == IntZero { - return NewErr("divide by zero") + val, err := divideInt64Checked(int64(i), int64(otherInt)) + if err != nil { + return wrapErr(err) } - // In twos complement, negating MinInt64 would result in a valid of MaxInt64+1. - if i == math.MinInt64 && otherInt == -1 { - return NewErr("integer overflow") - } - return i / otherInt + return Int(val) } // Equal implements ref.Val.Equal. func (i Int) Equal(other ref.Val) ref.Val { - otherInt, ok := other.(Int) - if !ok { - return ValOrErr(other, "no such overload") + switch ov := other.(type) { + case Double: + if math.IsNaN(float64(ov)) { + return False + } + return Bool(compareIntDouble(i, ov) == 0) + case Int: + return Bool(i == ov) + case Uint: + return Bool(compareIntUint(i, ov) == 0) + default: + return False } - return Bool(i == otherInt) } // Modulo implements traits.Modder.Modulo. func (i Int) Modulo(other ref.Val) ref.Val { otherInt, ok := other.(Int) if !ok { - return ValOrErr(other, "no such overload") + return MaybeNoSuchOverloadErr(other) } - if otherInt == IntZero { - return NewErr("modulus by zero") + val, err := moduloInt64Checked(int64(i), int64(otherInt)) + if err != nil { + return wrapErr(err) } - // In twos complement, negating MinInt64 would result in a valid of MaxInt64+1. - if i == math.MinInt64 && otherInt == -1 { - return NewErr("integer overflow") - } - return i % otherInt + return Int(val) } // Multiply implements traits.Multiplier.Multiply. func (i Int) Multiply(other ref.Val) ref.Val { otherInt, ok := other.(Int) if !ok { - return ValOrErr(other, "no such overload") + return MaybeNoSuchOverloadErr(other) } - // Detecting multiplication overflow is more complicated than the others. The first two detect - // attempting to negate MinInt64, which would result in MaxInt64+1. The other four detect normal - // overflow conditions. - if (i == -1 && otherInt == math.MinInt64) || (otherInt == -1 && i == math.MinInt64) || - (i > 0 && otherInt > 0 && i > math.MaxInt64/otherInt) || (i > 0 && otherInt < 0 && otherInt < math.MinInt64/i) || - (i < 0 && otherInt > 0 && i < math.MinInt64/otherInt) || (i < 0 && otherInt < 0 && otherInt < math.MaxInt64/i) { - return NewErr("integer overflow") + val, err := multiplyInt64Checked(int64(i), int64(otherInt)) + if err != nil { + return wrapErr(err) } - return i * otherInt + return Int(val) } // Negate implements traits.Negater.Negate. func (i Int) Negate() ref.Val { - // In twos complement, negating MinInt64 would result in a valid of MaxInt64+1. - if i == math.MinInt64 { - return NewErr("integer overflow") + val, err := negateInt64Checked(int64(i)) + if err != nil { + return wrapErr(err) } - return -i + return Int(val) } // Subtract implements traits.Subtractor.Subtract. func (i Int) Subtract(subtrahend ref.Val) ref.Val { subtraInt, ok := subtrahend.(Int) if !ok { - return ValOrErr(subtrahend, "no such overload") + return MaybeNoSuchOverloadErr(subtrahend) } - if (subtraInt < 0 && i > math.MaxInt64+subtraInt) || (subtraInt > 0 && i < math.MinInt64+subtraInt) { - return NewErr("integer overflow") + val, err := subtractInt64Checked(int64(i), int64(subtraInt)) + if err != nil { + return wrapErr(err) } - return i - subtraInt + return Int(val) } // Type implements ref.Val.Type. diff --git a/vendor/github.com/google/cel-go/common/types/json_value.go b/vendor/github.com/google/cel-go/common/types/json_value.go index cf7527884..cd63b5194 100644 --- a/vendor/github.com/google/cel-go/common/types/json_value.go +++ b/vendor/github.com/google/cel-go/common/types/json_value.go @@ -17,7 +17,7 @@ package types import ( "reflect" - "google.golang.org/protobuf/types/known/structpb" + structpb "google.golang.org/protobuf/types/known/structpb" ) // JSON type constants representing the reflected types of protobuf JSON values. diff --git a/vendor/github.com/google/cel-go/common/types/list.go b/vendor/github.com/google/cel-go/common/types/list.go index fd577e95d..7230f7ea1 100644 --- a/vendor/github.com/google/cel-go/common/types/list.go +++ b/vendor/github.com/google/cel-go/common/types/list.go @@ -20,7 +20,6 @@ import ( "github.com/google/cel-go/common/types/ref" "github.com/google/cel-go/common/types/traits" - "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" @@ -96,6 +95,20 @@ func NewJSONList(adapter ref.TypeAdapter, l *structpb.ListValue) traits.Lister { } } +// NewMutableList creates a new mutable list whose internal state can be modified. +func NewMutableList(adapter ref.TypeAdapter) traits.MutableLister { + var mutableValues []ref.Val + return &mutableList{ + baseList: &baseList{ + TypeAdapter: adapter, + value: mutableValues, + size: 0, + get: func(i int) interface{} { return mutableValues[i] }, + }, + mutableValues: mutableValues, + } +} + // baseList points to a list containing elements of any type. // The `value` is an array of native values, and refValue is its reflection object. // The `ref.TypeAdapter` enables native type to CEL type conversions. @@ -132,28 +145,14 @@ func (l *baseList) Add(other ref.Val) ref.Val { // Contains implements the traits.Container interface method. func (l *baseList) Contains(elem ref.Val) ref.Val { - if IsUnknownOrError(elem) { - return elem - } - var err ref.Val for i := 0; i < l.size; i++ { val := l.NativeToValue(l.get(i)) cmp := elem.Equal(val) b, ok := cmp.(Bool) - // When there is an error on the contain check, this is not necessarily terminal. - // The contains call could find the element and return True, just as though the user - // had written a per-element comparison in an exists() macro or logical ||, e.g. - // list.exists(e, e == elem) - if !ok && err == nil { - err = ValOrErr(cmp, "no such overload") - } - if b == True { + if ok && b == True { return True } } - if err != nil { - return err - } return False } @@ -223,7 +222,7 @@ func (l *baseList) ConvertToType(typeVal ref.Type) ref.Val { func (l *baseList) Equal(other ref.Val) ref.Val { otherList, ok := other.(traits.Lister) if !ok { - return MaybeNoSuchOverloadErr(other) + return False } if l.Size() != otherList.Size() { return False @@ -231,9 +230,9 @@ func (l *baseList) Equal(other ref.Val) ref.Val { for i := IntZero; i < l.Size().(Int); i++ { thisElem := l.Get(i) otherElem := otherList.Get(i) - elemEq := thisElem.Equal(otherElem) - if elemEq != True { - return elemEq + elemEq := Equal(thisElem, otherElem) + if elemEq == False { + return False } } return True @@ -241,16 +240,14 @@ func (l *baseList) Equal(other ref.Val) ref.Val { // Get implements the traits.Indexer interface method. func (l *baseList) Get(index ref.Val) ref.Val { - i, ok := index.(Int) - if !ok { - return ValOrErr(index, "unsupported index type '%s' in list", index.Type()) + ind, err := indexOrError(index) + if err != nil { + return ValOrErr(index, err.Error()) } - iv := int(i) - if iv < 0 || iv >= l.size { - return NewErr("index '%d' out of range in list size '%d'", i, l.Size()) + if ind < 0 || ind >= l.size { + return NewErr("index '%d' out of range in list size '%d'", ind, l.Size()) } - elem := l.get(iv) - return l.NativeToValue(elem) + return l.NativeToValue(l.get(ind)) } // Iterator implements the traits.Iterable interface method. @@ -273,6 +270,37 @@ func (l *baseList) Value() interface{} { return l.value } +// mutableList aggregates values into its internal storage. For use with internal CEL variables only. +type mutableList struct { + *baseList + mutableValues []ref.Val +} + +// Add copies elements from the other list into the internal storage of the mutable list. +// The ref.Val returned by Add is the receiver. +func (l *mutableList) Add(other ref.Val) ref.Val { + switch otherList := other.(type) { + case *mutableList: + l.mutableValues = append(l.mutableValues, otherList.mutableValues...) + l.size += len(otherList.mutableValues) + case traits.Lister: + for i := IntZero; i < otherList.Size().(Int); i++ { + l.size++ + l.mutableValues = append(l.mutableValues, otherList.Get(i)) + } + default: + return MaybeNoSuchOverloadErr(otherList) + } + return l +} + +// ToImmutableList returns an immutable list based on the internal storage of the mutable list. +func (l *mutableList) ToImmutableList() traits.Lister { + // The reference to internal state is guaranteed to be safe as this call is only performed + // when mutations have been completed. + return NewRefValList(l.TypeAdapter, l.mutableValues) +} + // concatList combines two list implementations together into a view. // The `ref.TypeAdapter` enables native type to CEL type conversions. type concatList struct { @@ -300,7 +328,7 @@ func (l *concatList) Add(other ref.Val) ref.Val { nextList: otherList} } -// Contains implments the traits.Container interface method. +// Contains implements the traits.Container interface method. func (l *concatList) Contains(elem ref.Val) ref.Val { // The concat list relies on the IsErrorOrUnknown checks against the input element to be // performed by the `prevList` and/or `nextList`. @@ -343,28 +371,36 @@ func (l *concatList) ConvertToType(typeVal ref.Type) ref.Val { func (l *concatList) Equal(other ref.Val) ref.Val { otherList, ok := other.(traits.Lister) if !ok { - return MaybeNoSuchOverloadErr(other) + return False } if l.Size() != otherList.Size() { return False } + var maybeErr ref.Val for i := IntZero; i < l.Size().(Int); i++ { thisElem := l.Get(i) otherElem := otherList.Get(i) - elemEq := thisElem.Equal(otherElem) - if elemEq != True { - return elemEq + elemEq := Equal(thisElem, otherElem) + if elemEq == False { + return False } + if maybeErr == nil && IsUnknownOrError(elemEq) { + maybeErr = elemEq + } + } + if maybeErr != nil { + return maybeErr } return True } // Get implements the traits.Indexer interface method. func (l *concatList) Get(index ref.Val) ref.Val { - i, ok := index.(Int) - if !ok { - return MaybeNoSuchOverloadErr(index) + ind, err := indexOrError(index) + if err != nil { + return ValOrErr(index, err.Error()) } + i := Int(ind) if i < l.prevList.Size().(Int) { return l.prevList.Get(i) } @@ -432,3 +468,22 @@ func (it *listIterator) Next() ref.Val { } return nil } + +func indexOrError(index ref.Val) (int, error) { + switch iv := index.(type) { + case Int: + return int(iv), nil + case Double: + if ik, ok := doubleToInt64Lossless(float64(iv)); ok { + return int(ik), nil + } + return -1, fmt.Errorf("unsupported index value %v in list", index) + case Uint: + if ik, ok := uint64ToInt64Lossless(uint64(iv)); ok { + return int(ik), nil + } + return -1, fmt.Errorf("unsupported index value %v in list", index) + default: + return -1, fmt.Errorf("unsupported index type '%s' in list", index.Type()) + } +} diff --git a/vendor/github.com/google/cel-go/common/types/map.go b/vendor/github.com/google/cel-go/common/types/map.go index 4c91f0da3..586559402 100644 --- a/vendor/github.com/google/cel-go/common/types/map.go +++ b/vendor/github.com/google/cel-go/common/types/map.go @@ -21,7 +21,6 @@ import ( "github.com/google/cel-go/common/types/pb" "github.com/google/cel-go/common/types/ref" "github.com/google/cel-go/common/types/traits" - "github.com/stoewer/go-strcase" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" @@ -106,11 +105,9 @@ var ( // This interface implements portions of the API surface area required by the traits.Mapper // interface. type mapAccessor interface { - // Find returns a value, if one exists, for the inpput key. + // Find returns a value, if one exists, for the input key. // // If the key is not found the function returns (nil, false). - // If the input key is not valid for the map, or is Err or Unknown the function returns - // (Unknown|Err, false). Find(ref.Val) (ref.Val, bool) // Iterator returns an Iterator over the map key set. @@ -136,11 +133,7 @@ type baseMap struct { // Contains implements the traits.Container interface method. func (m *baseMap) Contains(index ref.Val) ref.Val { - val, found := m.Find(index) - // When the index is not found and val is non-nil, this is an error or unknown value. - if !found && val != nil && IsUnknownOrError(val) { - return val - } + _, found := m.Find(index) return Bool(found) } @@ -252,7 +245,7 @@ func (m *baseMap) ConvertToType(typeVal ref.Type) ref.Val { func (m *baseMap) Equal(other ref.Val) ref.Val { otherMap, ok := other.(traits.Mapper) if !ok { - return MaybeNoSuchOverloadErr(other) + return False } if m.Size() != otherMap.Size() { return False @@ -263,14 +256,11 @@ func (m *baseMap) Equal(other ref.Val) ref.Val { thisVal, _ := m.Find(key) otherVal, found := otherMap.Find(key) if !found { - if otherVal == nil { - return False - } - return MaybeNoSuchOverloadErr(otherVal) + return False } - valEq := thisVal.Equal(otherVal) - if valEq != True { - return valEq + valEq := Equal(thisVal, otherVal) + if valEq == False { + return False } } return True @@ -316,12 +306,10 @@ type jsonStructAccessor struct { // found. // // If the key is not found the function returns (nil, false). -// If the input key is not a String, or is an Err or Unknown, the function returns -// (Unknown|Err, false). func (a *jsonStructAccessor) Find(key ref.Val) (ref.Val, bool) { strKey, ok := key.(String) if !ok { - return MaybeNoSuchOverloadErr(key), false + return nil, false } keyVal, found := a.st[string(strKey)] if !found { @@ -364,36 +352,58 @@ type reflectMapAccessor struct { // returning (value, true) if present. // // If the key is not found the function returns (nil, false). -// If the input key is not a String, or is an Err or Unknown, the function returns -// (Unknown|Err, false). -func (a *reflectMapAccessor) Find(key ref.Val) (ref.Val, bool) { - if IsUnknownOrError(key) { - return MaybeNoSuchOverloadErr(key), false - } - k, err := key.ConvertToNative(a.keyType) - if err != nil { - return &Err{err}, false - } - var refKey reflect.Value - switch k := k.(type) { - case reflect.Value: - refKey = k - default: - refKey = reflect.ValueOf(k) - } - val := a.refValue.MapIndex(refKey) - if !val.IsValid() { +func (m *reflectMapAccessor) Find(key ref.Val) (ref.Val, bool) { + if m.refValue.Len() == 0 { return nil, false } - return a.NativeToValue(val.Interface()), true + if keyVal, found := m.findInternal(key); found { + return keyVal, true + } + switch k := key.(type) { + // Double is not a valid proto map key type, so check for the key as an int or uint. + case Double: + if ik, ok := doubleToInt64Lossless(float64(k)); ok { + if keyVal, found := m.findInternal(Int(ik)); found { + return keyVal, true + } + } + if uk, ok := doubleToUint64Lossless(float64(k)); ok { + return m.findInternal(Uint(uk)) + } + // map keys of type double are not supported. + case Int: + if uk, ok := int64ToUint64Lossless(int64(k)); ok { + return m.findInternal(Uint(uk)) + } + case Uint: + if ik, ok := uint64ToInt64Lossless(uint64(k)); ok { + return m.findInternal(Int(ik)) + } + } + return nil, false +} + +// findInternal attempts to convert the incoming key to the map's internal native type +// and then returns the value, if found. +func (m *reflectMapAccessor) findInternal(key ref.Val) (ref.Val, bool) { + k, err := key.ConvertToNative(m.keyType) + if err != nil { + return nil, false + } + refKey := reflect.ValueOf(k) + val := m.refValue.MapIndex(refKey) + if val.IsValid() { + return m.NativeToValue(val.Interface()), true + } + return nil, false } // Iterator creates a Golang reflection based traits.Iterator. -func (a *reflectMapAccessor) Iterator() traits.Iterator { +func (m *reflectMapAccessor) Iterator() traits.Iterator { return &mapIterator{ - TypeAdapter: a.TypeAdapter, - mapKeys: a.refValue.MapKeys(), - len: a.refValue.Len(), + TypeAdapter: m.TypeAdapter, + mapKeys: m.refValue.MapRange(), + len: m.refValue.Len(), } } @@ -408,20 +418,44 @@ type refValMapAccessor struct { // Find uses native map accesses to find the key, returning (value, true) if present. // // If the key is not found the function returns (nil, false). -// If the input key is an Err or Unknown, the function returns (Unknown|Err, false). func (a *refValMapAccessor) Find(key ref.Val) (ref.Val, bool) { - if IsUnknownOrError(key) { - return key, false + if len(a.mapVal) == 0 { + return nil, false } - keyVal, found := a.mapVal[key] - return keyVal, found + if keyVal, found := a.mapVal[key]; found { + return keyVal, true + } + switch k := key.(type) { + case Double: + if ik, ok := doubleToInt64Lossless(float64(k)); ok { + if keyVal, found := a.mapVal[Int(ik)]; found { + return keyVal, found + } + } + if uk, ok := doubleToUint64Lossless(float64(k)); ok { + keyVal, found := a.mapVal[Uint(uk)] + return keyVal, found + } + // map keys of type double are not supported. + case Int: + if uk, ok := int64ToUint64Lossless(int64(k)); ok { + keyVal, found := a.mapVal[Uint(uk)] + return keyVal, found + } + case Uint: + if ik, ok := uint64ToInt64Lossless(uint64(k)); ok { + keyVal, found := a.mapVal[Int(ik)] + return keyVal, found + } + } + return nil, false } // Iterator produces a new traits.Iterator which iterates over the map keys via Golang reflection. func (a *refValMapAccessor) Iterator() traits.Iterator { return &mapIterator{ TypeAdapter: DefaultTypeAdapter, - mapKeys: reflect.ValueOf(a.mapVal).MapKeys(), + mapKeys: reflect.ValueOf(a.mapVal).MapRange(), len: len(a.mapVal), } } @@ -437,12 +471,10 @@ type stringMapAccessor struct { // Find uses native map accesses to find the key, returning (value, true) if present. // // If the key is not found the function returns (nil, false). -// If the input key is not a String, or is an Err or Unknown, the function returns -// (Unknown|Err, false). func (a *stringMapAccessor) Find(key ref.Val) (ref.Val, bool) { strKey, ok := key.(String) if !ok { - return MaybeNoSuchOverloadErr(key), false + return nil, false } keyVal, found := a.mapVal[string(strKey)] if !found { @@ -481,12 +513,10 @@ type stringIfaceMapAccessor struct { // Find uses native map accesses to find the key, returning (value, true) if present. // // If the key is not found the function returns (nil, false). -// If the input key is not a String, or is an Err or Unknown, the function returns -// (Unknown|Err, false). func (a *stringIfaceMapAccessor) Find(key ref.Val) (ref.Val, bool) { strKey, ok := key.(String) if !ok { - return MaybeNoSuchOverloadErr(key), false + return nil, false } keyVal, found := a.mapVal[string(strKey)] if !found { @@ -519,11 +549,7 @@ type protoMap struct { // Contains returns whether the map contains the given key. func (m *protoMap) Contains(key ref.Val) ref.Val { - val, found := m.Find(key) - // When the index is not found and val is non-nil, this is an error or unknown value. - if !found && val != nil && IsUnknownOrError(val) { - return val - } + _, found := m.Find(key) return Bool(found) } @@ -617,10 +643,10 @@ func (m *protoMap) ConvertToType(typeVal ref.Type) ref.Val { // Equal implements the ref.Val interface method. func (m *protoMap) Equal(other ref.Val) ref.Val { - if MapType != other.Type() { - return MaybeNoSuchOverloadErr(other) + otherMap, ok := other.(traits.Mapper) + if !ok { + return False } - otherMap := other.(traits.Mapper) if m.value.Map.Len() != int(otherMap.Size().(Int)) { return False } @@ -630,14 +656,10 @@ func (m *protoMap) Equal(other ref.Val) ref.Val { valVal := m.NativeToValue(val) otherVal, found := otherMap.Find(keyVal) if !found { - if otherVal == nil { - retVal = False - return false - } - retVal = MaybeNoSuchOverloadErr(otherVal) + retVal = False return false } - valEq := valVal.Equal(otherVal) + valEq := Equal(valVal, otherVal) if valEq != True { retVal = valEq return false @@ -650,17 +672,41 @@ func (m *protoMap) Equal(other ref.Val) ref.Val { // Find returns whether the protoreflect.Map contains the input key. // // If the key is not found the function returns (nil, false). -// If the input key is not a supported proto map key type, or is an Err or Unknown, -// the function returns -// (Unknown|Err, false). func (m *protoMap) Find(key ref.Val) (ref.Val, bool) { - if IsUnknownOrError(key) { - return key, false + if keyVal, found := m.findInternal(key); found { + return keyVal, true } + switch k := key.(type) { + // Double is not a valid proto map key type, so check for the key as an int or uint. + case Double: + if ik, ok := doubleToInt64Lossless(float64(k)); ok { + if keyVal, found := m.findInternal(Int(ik)); found { + return keyVal, true + } + } + if uk, ok := doubleToUint64Lossless(float64(k)); ok { + return m.findInternal(Uint(uk)) + } + // map keys of type double are not supported. + case Int: + if uk, ok := int64ToUint64Lossless(int64(k)); ok { + return m.findInternal(Uint(uk)) + } + case Uint: + if ik, ok := uint64ToInt64Lossless(uint64(k)); ok { + return m.findInternal(Int(ik)) + } + } + return nil, false +} + +// findInternal attempts to convert the incoming key to the map's internal native type +// and then returns the value, if found. +func (m *protoMap) findInternal(key ref.Val) (ref.Val, bool) { // Convert the input key to the expected protobuf key type. ntvKey, err := key.ConvertToNative(m.value.KeyType.ReflectType()) if err != nil { - return &Err{err}, false + return nil, false } // Use protoreflection to get the key value. val := m.value.Get(protoreflect.ValueOf(ntvKey).MapKey()) @@ -671,7 +717,7 @@ func (m *protoMap) Find(key ref.Val) (ref.Val, bool) { switch v := val.Interface().(type) { case protoreflect.List, protoreflect.Map: // Maps do not support list or map values - return NewErr("unsupported map element type: (%T)%v", v, v), false + return nil, false default: return m.NativeToValue(v), true } @@ -719,7 +765,7 @@ func (m *protoMap) Value() interface{} { type mapIterator struct { *baseIterator ref.TypeAdapter - mapKeys []reflect.Value + mapKeys *reflect.MapIter cursor int len int } @@ -731,10 +777,9 @@ func (it *mapIterator) HasNext() ref.Val { // Next implements the traits.Iterator interface method. func (it *mapIterator) Next() ref.Val { - if it.HasNext() == True { - index := it.cursor + if it.HasNext() == True && it.mapKeys.Next() { it.cursor++ - refKey := it.mapKeys[index] + refKey := it.mapKeys.Key() return it.NativeToValue(refKey.Interface()) } return nil diff --git a/vendor/github.com/google/cel-go/common/types/null.go b/vendor/github.com/google/cel-go/common/types/null.go index 3dc688856..3d3503c27 100644 --- a/vendor/github.com/google/cel-go/common/types/null.go +++ b/vendor/github.com/google/cel-go/common/types/null.go @@ -18,9 +18,8 @@ import ( "fmt" "reflect" - "google.golang.org/protobuf/proto" - "github.com/google/cel-go/common/types/ref" + "google.golang.org/protobuf/proto" anypb "google.golang.org/protobuf/types/known/anypb" structpb "google.golang.org/protobuf/types/known/structpb" @@ -84,10 +83,7 @@ func (n Null) ConvertToType(typeVal ref.Type) ref.Val { // Equal implements ref.Val.Equal. func (n Null) Equal(other ref.Val) ref.Val { - if NullType != other.Type() { - return ValOrErr(other, "no such overload") - } - return True + return Bool(NullType == other.Type()) } // Type implements ref.Val.Type. diff --git a/vendor/github.com/google/cel-go/common/types/object.go b/vendor/github.com/google/cel-go/common/types/object.go index e77b078fa..5e4212fa3 100644 --- a/vendor/github.com/google/cel-go/common/types/object.go +++ b/vendor/github.com/google/cel-go/common/types/object.go @@ -20,7 +20,6 @@ import ( "github.com/google/cel-go/common/types/pb" "github.com/google/cel-go/common/types/ref" - "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" @@ -110,10 +109,8 @@ func (o *protoObj) ConvertToType(typeVal ref.Type) ref.Val { } func (o *protoObj) Equal(other ref.Val) ref.Val { - if o.typeDesc.Name() != other.Type().TypeName() { - return MaybeNoSuchOverloadErr(other) - } - return Bool(proto.Equal(o.value, other.Value().(proto.Message))) + otherPB, ok := other.Value().(proto.Message) + return Bool(ok && pb.Equal(o.value, otherPB)) } // IsSet tests whether a field which is defined is set to a non-default value. diff --git a/vendor/github.com/google/cel-go/common/types/overflow.go b/vendor/github.com/google/cel-go/common/types/overflow.go new file mode 100644 index 000000000..c68a92182 --- /dev/null +++ b/vendor/github.com/google/cel-go/common/types/overflow.go @@ -0,0 +1,389 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "math" + "time" +) + +var ( + doubleTwoTo64 = math.Ldexp(1.0, 64) +) + +// addInt64Checked performs addition with overflow detection of two int64 values. +// +// If the operation fails the error return value will be non-nil. +func addInt64Checked(x, y int64) (int64, error) { + if (y > 0 && x > math.MaxInt64-y) || (y < 0 && x < math.MinInt64-y) { + return 0, errIntOverflow + } + return x + y, nil +} + +// subtractInt64Checked performs subtraction with overflow detection of two int64 values. +// +// If the operation fails the error return value will be non-nil. +func subtractInt64Checked(x, y int64) (int64, error) { + if (y < 0 && x > math.MaxInt64+y) || (y > 0 && x < math.MinInt64+y) { + return 0, errIntOverflow + } + return x - y, nil +} + +// negateInt64Checked performs negation with overflow detection of an int64. +// +// If the operation fails the error return value will be non-nil. +func negateInt64Checked(x int64) (int64, error) { + // In twos complement, negating MinInt64 would result in a valid of MaxInt64+1. + if x == math.MinInt64 { + return 0, errIntOverflow + } + return -x, nil +} + +// multiplyInt64Checked performs multiplication with overflow detection of two int64 value. +// +// If the operation fails the error return value will be non-nil. +func multiplyInt64Checked(x, y int64) (int64, error) { + // Detecting multiplication overflow is more complicated than the others. The first two detect + // attempting to negate MinInt64, which would result in MaxInt64+1. The other four detect normal + // overflow conditions. + if (x == -1 && y == math.MinInt64) || (y == -1 && x == math.MinInt64) || + // x is positive, y is positive + (x > 0 && y > 0 && x > math.MaxInt64/y) || + // x is positive, y is negative + (x > 0 && y < 0 && y < math.MinInt64/x) || + // x is negative, y is positive + (x < 0 && y > 0 && x < math.MinInt64/y) || + // x is negative, y is negative + (x < 0 && y < 0 && y < math.MaxInt64/x) { + return 0, errIntOverflow + } + return x * y, nil +} + +// divideInt64Checked performs division with overflow detection of two int64 values, +// as well as a division by zero check. +// +// If the operation fails the error return value will be non-nil. +func divideInt64Checked(x, y int64) (int64, error) { + // Division by zero. + if y == 0 { + return 0, errDivideByZero + } + // In twos complement, negating MinInt64 would result in a valid of MaxInt64+1. + if x == math.MinInt64 && y == -1 { + return 0, errIntOverflow + } + return x / y, nil +} + +// moduloInt64Checked performs modulo with overflow detection of two int64 values +// as well as a modulus by zero check. +// +// If the operation fails the error return value will be non-nil. +func moduloInt64Checked(x, y int64) (int64, error) { + // Modulus by zero. + if y == 0 { + return 0, errModulusByZero + } + // In twos complement, negating MinInt64 would result in a valid of MaxInt64+1. + if x == math.MinInt64 && y == -1 { + return 0, errIntOverflow + } + return x % y, nil +} + +// addUint64Checked performs addition with overflow detection of two uint64 values. +// +// If the operation fails due to overflow the error return value will be non-nil. +func addUint64Checked(x, y uint64) (uint64, error) { + if y > 0 && x > math.MaxUint64-y { + return 0, errUintOverflow + } + return x + y, nil +} + +// subtractUint64Checked performs subtraction with overflow detection of two uint64 values. +// +// If the operation fails due to overflow the error return value will be non-nil. +func subtractUint64Checked(x, y uint64) (uint64, error) { + if y > x { + return 0, errUintOverflow + } + return x - y, nil +} + +// multiplyUint64Checked performs multiplication with overflow detection of two uint64 values. +// +// If the operation fails due to overflow the error return value will be non-nil. +func multiplyUint64Checked(x, y uint64) (uint64, error) { + if y != 0 && x > math.MaxUint64/y { + return 0, errUintOverflow + } + return x * y, nil +} + +// divideUint64Checked performs division with a test for division by zero. +// +// If the operation fails the error return value will be non-nil. +func divideUint64Checked(x, y uint64) (uint64, error) { + if y == 0 { + return 0, errDivideByZero + } + return x / y, nil +} + +// moduloUint64Checked performs modulo with a test for modulus by zero. +// +// If the operation fails the error return value will be non-nil. +func moduloUint64Checked(x, y uint64) (uint64, error) { + if y == 0 { + return 0, errModulusByZero + } + return x % y, nil +} + +// addDurationChecked performs addition with overflow detection of two time.Durations. +// +// If the operation fails due to overflow the error return value will be non-nil. +func addDurationChecked(x, y time.Duration) (time.Duration, error) { + val, err := addInt64Checked(int64(x), int64(y)) + if err != nil { + return time.Duration(0), err + } + return time.Duration(val), nil +} + +// subtractDurationChecked performs subtraction with overflow detection of two time.Durations. +// +// If the operation fails due to overflow the error return value will be non-nil. +func subtractDurationChecked(x, y time.Duration) (time.Duration, error) { + val, err := subtractInt64Checked(int64(x), int64(y)) + if err != nil { + return time.Duration(0), err + } + return time.Duration(val), nil +} + +// negateDurationChecked performs negation with overflow detection of a time.Duration. +// +// If the operation fails due to overflow the error return value will be non-nil. +func negateDurationChecked(x time.Duration) (time.Duration, error) { + val, err := negateInt64Checked(int64(x)) + if err != nil { + return time.Duration(0), err + } + return time.Duration(val), nil +} + +// addDurationChecked performs addition with overflow detection of a time.Time and time.Duration. +// +// If the operation fails due to overflow the error return value will be non-nil. +func addTimeDurationChecked(x time.Time, y time.Duration) (time.Time, error) { + // This is tricky. A time is represented as (int64, int32) where the first is seconds and second + // is nanoseconds. A duration is int64 representing nanoseconds. We cannot normalize time to int64 + // as it could potentially overflow. The only way to proceed is to break time and duration into + // second and nanosecond components. + + // First we break time into its components by truncating and subtracting. + sec1 := x.Truncate(time.Second).Unix() // Truncate to seconds. + nsec1 := x.Sub(x.Truncate(time.Second)).Nanoseconds() // Get nanoseconds by truncating and subtracting. + + // Second we break duration into its components by dividing and modulo. + sec2 := int64(y) / int64(time.Second) // Truncate to seconds. + nsec2 := int64(y) % int64(time.Second) // Get remainder. + + // Add seconds first, detecting any overflow. + sec, err := addInt64Checked(sec1, sec2) + if err != nil { + return time.Time{}, err + } + // Nanoseconds cannot overflow as time.Time normalizes them to [0, 999999999]. + nsec := nsec1 + nsec2 + + // We need to normalize nanoseconds to be positive and carry extra nanoseconds to seconds. + // Adapted from time.Unix(int64, int64). + if nsec < 0 || nsec >= int64(time.Second) { + // Add seconds. + sec, err = addInt64Checked(sec, nsec/int64(time.Second)) + if err != nil { + return time.Time{}, err + } + + nsec -= (nsec / int64(time.Second)) * int64(time.Second) + if nsec < 0 { + // Subtract an extra second + sec, err = addInt64Checked(sec, -1) + if err != nil { + return time.Time{}, err + } + nsec += int64(time.Second) + } + } + + // Check if the the number of seconds from Unix epoch is within our acceptable range. + if sec < minUnixTime || sec > maxUnixTime { + return time.Time{}, errTimestampOverflow + } + + // Return resulting time and propagate time zone. + return time.Unix(sec, nsec).In(x.Location()), nil +} + +// subtractTimeChecked performs subtraction with overflow detection of two time.Time. +// +// If the operation fails due to overflow the error return value will be non-nil. +func subtractTimeChecked(x, y time.Time) (time.Duration, error) { + // Similar to addTimeDurationOverflow() above. + + // First we break time into its components by truncating and subtracting. + sec1 := x.Truncate(time.Second).Unix() // Truncate to seconds. + nsec1 := x.Sub(x.Truncate(time.Second)).Nanoseconds() // Get nanoseconds by truncating and subtracting. + + // Second we break duration into its components by truncating and subtracting. + sec2 := y.Truncate(time.Second).Unix() // Truncate to seconds. + nsec2 := y.Sub(y.Truncate(time.Second)).Nanoseconds() // Get nanoseconds by truncating and subtracting. + + // Subtract seconds first, detecting any overflow. + sec, err := subtractInt64Checked(sec1, sec2) + if err != nil { + return time.Duration(0), err + } + + // Nanoseconds cannot overflow as time.Time normalizes them to [0, 999999999]. + nsec := nsec1 - nsec2 + + // Scale seconds to nanoseconds detecting overflow. + tsec, err := multiplyInt64Checked(sec, int64(time.Second)) + if err != nil { + return time.Duration(0), err + } + + // Lastly we need to add the two nanoseconds together. + val, err := addInt64Checked(tsec, nsec) + if err != nil { + return time.Duration(0), err + } + + return time.Duration(val), nil +} + +// subtractTimeDurationChecked performs subtraction with overflow detection of a time.Time and +// time.Duration. +// +// If the operation fails due to overflow the error return value will be non-nil. +func subtractTimeDurationChecked(x time.Time, y time.Duration) (time.Time, error) { + // The easiest way to implement this is to negate y and add them. + // x - y = x + -y + val, err := negateDurationChecked(y) + if err != nil { + return time.Time{}, err + } + return addTimeDurationChecked(x, val) +} + +// doubleToInt64Checked converts a double to an int64 value. +// +// If the conversion fails due to overflow the error return value will be non-nil. +func doubleToInt64Checked(v float64) (int64, error) { + if math.IsInf(v, 0) || math.IsNaN(v) || v <= float64(math.MinInt64) || v >= float64(math.MaxInt64) { + return 0, errIntOverflow + } + return int64(v), nil +} + +// doubleToInt64Checked converts a double to a uint64 value. +// +// If the conversion fails due to overflow the error return value will be non-nil. +func doubleToUint64Checked(v float64) (uint64, error) { + if math.IsInf(v, 0) || math.IsNaN(v) || v < 0 || v >= doubleTwoTo64 { + return 0, errUintOverflow + } + return uint64(v), nil +} + +// int64ToUint64Checked converts an int64 to a uint64 value. +// +// If the conversion fails due to overflow the error return value will be non-nil. +func int64ToUint64Checked(v int64) (uint64, error) { + if v < 0 { + return 0, errUintOverflow + } + return uint64(v), nil +} + +// int64ToInt32Checked converts an int64 to an int32 value. +// +// If the conversion fails due to overflow the error return value will be non-nil. +func int64ToInt32Checked(v int64) (int32, error) { + if v < math.MinInt32 || v > math.MaxInt32 { + return 0, errIntOverflow + } + return int32(v), nil +} + +// uint64ToUint32Checked converts a uint64 to a uint32 value. +// +// If the conversion fails due to overflow the error return value will be non-nil. +func uint64ToUint32Checked(v uint64) (uint32, error) { + if v > math.MaxUint32 { + return 0, errUintOverflow + } + return uint32(v), nil +} + +// uint64ToInt64Checked converts a uint64 to an int64 value. +// +// If the conversion fails due to overflow the error return value will be non-nil. +func uint64ToInt64Checked(v uint64) (int64, error) { + if v > math.MaxInt64 { + return 0, errIntOverflow + } + return int64(v), nil +} + +func doubleToUint64Lossless(v float64) (uint64, bool) { + u, err := doubleToUint64Checked(v) + if err != nil { + return 0, false + } + if float64(u) != v { + return 0, false + } + return u, true +} + +func doubleToInt64Lossless(v float64) (int64, bool) { + i, err := doubleToInt64Checked(v) + if err != nil { + return 0, false + } + if float64(i) != v { + return 0, false + } + return i, true +} + +func int64ToUint64Lossless(v int64) (uint64, bool) { + u, err := int64ToUint64Checked(v) + return u, err == nil +} + +func uint64ToInt64Lossless(v uint64) (int64, bool) { + i, err := uint64ToInt64Checked(v) + return i, err == nil +} diff --git a/vendor/github.com/google/cel-go/common/types/pb/equal.go b/vendor/github.com/google/cel-go/common/types/pb/equal.go new file mode 100644 index 000000000..392a94961 --- /dev/null +++ b/vendor/github.com/google/cel-go/common/types/pb/equal.go @@ -0,0 +1,205 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pb + +import ( + "bytes" + "reflect" + + "google.golang.org/protobuf/encoding/protowire" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/known/anypb" +) + +// Equal returns whether two proto.Message instances are equal using the following criteria: +// +// - Messages must share the same instance of the type descriptor +// - Known set fields are compared using semantics equality +// - Bytes are compared using bytes.Equal +// - Scalar values are compared with operator == +// - List and map types are equal if they have the same length and all elements are equal +// - Messages are equal if they share the same descriptor and all set fields are equal +// - Unknown fields are compared using byte equality +// - NaN values are not equal to each other +// - google.protobuf.Any values are unpacked before comparison +// - If the type descriptor for a protobuf.Any cannot be found, byte equality is used rather than +// semantic equality. +// +// This method of proto equality mirrors the behavior of the C++ protobuf MessageDifferencer +// whereas the golang proto.Equal implementation mirrors the Java protobuf equals() methods +// behaviors which needed to treat NaN values as equal due to Java semantics. +func Equal(x, y proto.Message) bool { + if x == nil || y == nil { + return x == nil && y == nil + } + xRef := x.ProtoReflect() + yRef := y.ProtoReflect() + return equalMessage(xRef, yRef) +} + +func equalMessage(mx, my protoreflect.Message) bool { + // Note, the original proto.Equal upon which this implementation is based does not specifically handle the + // case when both messages are invalid. It is assumed that the descriptors will be equal and that byte-wise + // comparison will be used, though the semantics of validity are neither clear, nor promised within the + // proto.Equal implementation. + if mx.IsValid() != my.IsValid() || mx.Descriptor() != my.Descriptor() { + return false + } + + // This is an innovation on the default proto.Equal where protobuf.Any values are unpacked before comparison + // as otherwise the Any values are compared by bytes rather than structurally. + if isAny(mx) && isAny(my) { + ax := mx.Interface().(*anypb.Any) + ay := my.Interface().(*anypb.Any) + // If the values are not the same type url, return false. + if ax.GetTypeUrl() != ay.GetTypeUrl() { + return false + } + // If the values are byte equal, then return true. + if bytes.Equal(ax.GetValue(), ay.GetValue()) { + return true + } + // Otherwise fall through to the semantic comparison of the any values. + x, err := ax.UnmarshalNew() + if err != nil { + return false + } + y, err := ay.UnmarshalNew() + if err != nil { + return false + } + // Recursively compare the unwrapped messages to ensure nested Any values are unwrapped accordingly. + return equalMessage(x.ProtoReflect(), y.ProtoReflect()) + } + + // Walk the set fields to determine field-wise equality + nx := 0 + equal := true + mx.Range(func(fd protoreflect.FieldDescriptor, vx protoreflect.Value) bool { + nx++ + equal = my.Has(fd) && equalField(fd, vx, my.Get(fd)) + return equal + }) + if !equal { + return false + } + // Establish the count of set fields on message y + ny := 0 + my.Range(func(protoreflect.FieldDescriptor, protoreflect.Value) bool { + ny++ + return true + }) + // If the number of set fields is not equal return false. + if nx != ny { + return false + } + + return equalUnknown(mx.GetUnknown(), my.GetUnknown()) +} + +func equalField(fd protoreflect.FieldDescriptor, x, y protoreflect.Value) bool { + switch { + case fd.IsMap(): + return equalMap(fd, x.Map(), y.Map()) + case fd.IsList(): + return equalList(fd, x.List(), y.List()) + default: + return equalValue(fd, x, y) + } +} + +func equalMap(fd protoreflect.FieldDescriptor, x, y protoreflect.Map) bool { + if x.Len() != y.Len() { + return false + } + equal := true + x.Range(func(k protoreflect.MapKey, vx protoreflect.Value) bool { + vy := y.Get(k) + equal = y.Has(k) && equalValue(fd.MapValue(), vx, vy) + return equal + }) + return equal +} + +func equalList(fd protoreflect.FieldDescriptor, x, y protoreflect.List) bool { + if x.Len() != y.Len() { + return false + } + for i := x.Len() - 1; i >= 0; i-- { + if !equalValue(fd, x.Get(i), y.Get(i)) { + return false + } + } + return true +} + +func equalValue(fd protoreflect.FieldDescriptor, x, y protoreflect.Value) bool { + switch fd.Kind() { + case protoreflect.BoolKind: + return x.Bool() == y.Bool() + case protoreflect.EnumKind: + return x.Enum() == y.Enum() + case protoreflect.Int32Kind, protoreflect.Sint32Kind, + protoreflect.Int64Kind, protoreflect.Sint64Kind, + protoreflect.Sfixed32Kind, protoreflect.Sfixed64Kind: + return x.Int() == y.Int() + case protoreflect.Uint32Kind, protoreflect.Uint64Kind, + protoreflect.Fixed32Kind, protoreflect.Fixed64Kind: + return x.Uint() == y.Uint() + case protoreflect.FloatKind, protoreflect.DoubleKind: + return x.Float() == y.Float() + case protoreflect.StringKind: + return x.String() == y.String() + case protoreflect.BytesKind: + return bytes.Equal(x.Bytes(), y.Bytes()) + case protoreflect.MessageKind, protoreflect.GroupKind: + return equalMessage(x.Message(), y.Message()) + default: + return x.Interface() == y.Interface() + } +} + +func equalUnknown(x, y protoreflect.RawFields) bool { + lenX := len(x) + lenY := len(y) + if lenX != lenY { + return false + } + if lenX == 0 { + return true + } + if bytes.Equal([]byte(x), []byte(y)) { + return true + } + + mx := make(map[protoreflect.FieldNumber]protoreflect.RawFields) + my := make(map[protoreflect.FieldNumber]protoreflect.RawFields) + for len(x) > 0 { + fnum, _, n := protowire.ConsumeField(x) + mx[fnum] = append(mx[fnum], x[:n]...) + x = x[n:] + } + for len(y) > 0 { + fnum, _, n := protowire.ConsumeField(y) + my[fnum] = append(my[fnum], y[:n]...) + y = y[n:] + } + return reflect.DeepEqual(mx, my) +} + +func isAny(m protoreflect.Message) bool { + return string(m.Descriptor().FullName()) == "google.protobuf.Any" +} diff --git a/vendor/github.com/google/cel-go/common/types/pb/type.go b/vendor/github.com/google/cel-go/common/types/pb/type.go index c5060a468..8594008b1 100644 --- a/vendor/github.com/google/cel-go/common/types/pb/type.go +++ b/vendor/github.com/google/cel-go/common/types/pb/type.go @@ -27,7 +27,7 @@ import ( dpb "google.golang.org/protobuf/types/known/durationpb" structpb "google.golang.org/protobuf/types/known/structpb" tpb "google.golang.org/protobuf/types/known/timestamppb" - "google.golang.org/protobuf/types/known/wrapperspb" + wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" ) // description is a private interface used to make it convenient to perform type unwrapping at diff --git a/vendor/github.com/google/cel-go/common/types/provider.go b/vendor/github.com/google/cel-go/common/types/provider.go index 62be9f00c..3ab30b763 100644 --- a/vendor/github.com/google/cel-go/common/types/provider.go +++ b/vendor/github.com/google/cel-go/common/types/provider.go @@ -22,7 +22,6 @@ import ( "github.com/google/cel-go/common/types/pb" "github.com/google/cel-go/common/types/ref" "github.com/google/cel-go/common/types/traits" - "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" diff --git a/vendor/github.com/google/cel-go/common/types/string.go b/vendor/github.com/google/cel-go/common/types/string.go index 792c1781f..b6d665683 100644 --- a/vendor/github.com/google/cel-go/common/types/string.go +++ b/vendor/github.com/google/cel-go/common/types/string.go @@ -57,7 +57,7 @@ var ( func (s String) Add(other ref.Val) ref.Val { otherString, ok := other.(String) if !ok { - return ValOrErr(other, "no such overload") + return MaybeNoSuchOverloadErr(other) } return s + otherString } @@ -66,7 +66,7 @@ func (s String) Add(other ref.Val) ref.Val { func (s String) Compare(other ref.Val) ref.Val { otherString, ok := other.(String) if !ok { - return ValOrErr(other, "no such overload") + return MaybeNoSuchOverloadErr(other) } return Int(strings.Compare(s.Value().(string), otherString.Value().(string))) } @@ -131,11 +131,14 @@ func (s String) ConvertToType(typeVal ref.Type) ref.Val { return Bytes(s) case DurationType: if d, err := time.ParseDuration(s.Value().(string)); err == nil { - return Duration{Duration: d} + return durationOf(d) } case TimestampType: if t, err := time.Parse(time.RFC3339, s.Value().(string)); err == nil { - return Timestamp{Time: t} + if t.Unix() < minUnixTime || t.Unix() > maxUnixTime { + return celErrTimestampOverflow + } + return timestampOf(t) } case StringType: return s @@ -148,17 +151,14 @@ func (s String) ConvertToType(typeVal ref.Type) ref.Val { // Equal implements ref.Val.Equal. func (s String) Equal(other ref.Val) ref.Val { otherString, ok := other.(String) - if !ok { - return ValOrErr(other, "no such overload") - } - return Bool(s == otherString) + return Bool(ok && s == otherString) } // Match implements traits.Matcher.Match. func (s String) Match(pattern ref.Val) ref.Val { pat, ok := pattern.(String) if !ok { - return ValOrErr(pattern, "no such overload") + return MaybeNoSuchOverloadErr(pattern) } matched, err := regexp.MatchString(pat.Value().(string), s.Value().(string)) if err != nil { @@ -167,7 +167,7 @@ func (s String) Match(pattern ref.Val) ref.Val { return Bool(matched) } -// Receive implements traits.Reciever.Receive. +// Receive implements traits.Receiver.Receive. func (s String) Receive(function string, overload string, args []ref.Val) ref.Val { switch len(args) { case 1: @@ -175,7 +175,7 @@ func (s String) Receive(function string, overload string, args []ref.Val) ref.Va return f(s, args[0]) } } - return NewErr("no such overload") + return NoSuchOverloadErr() } // Size implements traits.Sizer.Size. @@ -196,7 +196,7 @@ func (s String) Value() interface{} { func stringContains(s String, sub ref.Val) ref.Val { subStr, ok := sub.(String) if !ok { - return ValOrErr(sub, "no such overload") + return MaybeNoSuchOverloadErr(sub) } return Bool(strings.Contains(string(s), string(subStr))) } @@ -204,7 +204,7 @@ func stringContains(s String, sub ref.Val) ref.Val { func stringEndsWith(s String, suf ref.Val) ref.Val { sufStr, ok := suf.(String) if !ok { - return ValOrErr(suf, "no such overload") + return MaybeNoSuchOverloadErr(suf) } return Bool(strings.HasSuffix(string(s), string(sufStr))) } @@ -212,7 +212,7 @@ func stringEndsWith(s String, suf ref.Val) ref.Val { func stringStartsWith(s String, pre ref.Val) ref.Val { preStr, ok := pre.(String) if !ok { - return ValOrErr(pre, "no such overload") + return MaybeNoSuchOverloadErr(pre) } return Bool(strings.HasPrefix(string(s), string(preStr))) } diff --git a/vendor/github.com/google/cel-go/common/types/timestamp.go b/vendor/github.com/google/cel-go/common/types/timestamp.go index a2e6e1ab7..cb3237447 100644 --- a/vendor/github.com/google/cel-go/common/types/timestamp.go +++ b/vendor/github.com/google/cel-go/common/types/timestamp.go @@ -37,6 +37,22 @@ type Timestamp struct { time.Time } +func timestampOf(t time.Time) Timestamp { + // Note that this function does not validate that time.Time is in our supported range. + return Timestamp{Time: t} +} + +const ( + // The number of seconds between year 1 and year 1970. This is borrowed from + // https://golang.org/src/time/time.go. + unixToInternal int64 = (1969*365 + 1969/4 - 1969/100 + 1969/400) * (60 * 60 * 24) + + // Number of seconds between `0001-01-01T00:00:00Z` and the Unix epoch. + minUnixTime int64 = -62135596800 + // Number of seconds between `9999-12-31T23:59:59.999999999Z` and the Unix epoch. + maxUnixTime int64 = 253402300799 +) + var ( // TimestampType singleton. TimestampType = NewTypeValue("google.protobuf.Timestamp", @@ -52,24 +68,24 @@ func (t Timestamp) Add(other ref.Val) ref.Val { case DurationType: return other.(Duration).Add(t) } - return ValOrErr(other, "no such overload") + return MaybeNoSuchOverloadErr(other) } // Compare implements traits.Comparer.Compare. func (t Timestamp) Compare(other ref.Val) ref.Val { if TimestampType != other.Type() { - return ValOrErr(other, "no such overload") + return MaybeNoSuchOverloadErr(other) } ts1 := t.Time ts2 := other.(Timestamp).Time - ts := ts1.Sub(ts2) - if ts < 0 { + switch { + case ts1.Before(ts2): return IntNegOne - } - if ts > 0 { + case ts1.After(ts2): return IntOne + default: + return IntZero } - return IntZero } // ConvertToNative implements ref.Val.ConvertToNative. @@ -104,7 +120,7 @@ func (t Timestamp) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { func (t Timestamp) ConvertToType(typeVal ref.Type) ref.Val { switch typeVal { case StringType: - return String(t.Format(time.RFC3339)) + return String(t.Format(time.RFC3339Nano)) case IntType: // Return the Unix time in seconds since 1970 return Int(t.Unix()) @@ -118,13 +134,11 @@ func (t Timestamp) ConvertToType(typeVal ref.Type) ref.Val { // Equal implements ref.Val.Equal. func (t Timestamp) Equal(other ref.Val) ref.Val { - if TimestampType != other.Type() { - return MaybeNoSuchOverloadErr(other) - } - return Bool(t.Time.Equal(other.(Timestamp).Time)) + otherTime, ok := other.(Timestamp) + return Bool(ok && t.Time.Equal(otherTime.Time)) } -// Receive implements traits.Reciever.Receive. +// Receive implements traits.Receiver.Receive. func (t Timestamp) Receive(function string, overload string, args []ref.Val) ref.Val { switch len(args) { case 0: @@ -136,7 +150,7 @@ func (t Timestamp) Receive(function string, overload string, args []ref.Val) ref return f(t.Time, args[0]) } } - return NewErr("no such overload") + return NoSuchOverloadErr() } // Subtract implements traits.Subtractor.Subtract. @@ -144,12 +158,20 @@ func (t Timestamp) Subtract(subtrahend ref.Val) ref.Val { switch subtrahend.Type() { case DurationType: dur := subtrahend.(Duration) - return Timestamp{Time: t.Time.Add(-dur.Duration)} + val, err := subtractTimeDurationChecked(t.Time, dur.Duration) + if err != nil { + return wrapErr(err) + } + return timestampOf(val) case TimestampType: t2 := subtrahend.(Timestamp).Time - return Duration{Duration: t.Time.Sub(t2)} + val, err := subtractTimeChecked(t.Time, t2) + if err != nil { + return wrapErr(err) + } + return durationOf(val) } - return ValOrErr(subtrahend, "no such overload") + return MaybeNoSuchOverloadErr(subtrahend) } // Type implements ref.Val.Type. @@ -259,14 +281,14 @@ func timestampGetMillisecondsWithTz(t time.Time, tz ref.Val) ref.Val { func timeZone(tz ref.Val, visitor timestampVisitor) timestampVisitor { return func(t time.Time) ref.Val { if StringType != tz.Type() { - return ValOrErr(tz, "no such overload") + return MaybeNoSuchOverloadErr(tz) } val := string(tz.(String)) ind := strings.Index(val, ":") if ind == -1 { loc, err := time.LoadLocation(val) if err != nil { - return &Err{err} + return wrapErr(err) } return visitor(t.In(loc)) } @@ -275,11 +297,11 @@ func timeZone(tz ref.Val, visitor timestampVisitor) timestampVisitor { // in the format ^(+|-)(0[0-9]|1[0-4]):[0-5][0-9]$. The numerical input is parsed in terms of hours and minutes. hr, err := strconv.Atoi(string(val[0:ind])) if err != nil { - return &Err{err} + return wrapErr(err) } min, err := strconv.Atoi(string(val[ind+1])) if err != nil { - return &Err{err} + return wrapErr(err) } var offset int if string(val[0]) == "-" { diff --git a/vendor/github.com/google/cel-go/common/types/traits/lister.go b/vendor/github.com/google/cel-go/common/types/traits/lister.go index 7b05c301d..5cf2593f3 100644 --- a/vendor/github.com/google/cel-go/common/types/traits/lister.go +++ b/vendor/github.com/google/cel-go/common/types/traits/lister.go @@ -25,3 +25,9 @@ type Lister interface { Iterable Sizer } + +// MutableLister interface which emits an immutable result after an intermediate computation. +type MutableLister interface { + Lister + ToImmutableList() Lister +} diff --git a/vendor/github.com/google/cel-go/common/types/type.go b/vendor/github.com/google/cel-go/common/types/type.go index a7253270a..21160974b 100644 --- a/vendor/github.com/google/cel-go/common/types/type.go +++ b/vendor/github.com/google/cel-go/common/types/type.go @@ -71,10 +71,8 @@ func (t *TypeValue) ConvertToType(typeVal ref.Type) ref.Val { // Equal implements ref.Val.Equal. func (t *TypeValue) Equal(other ref.Val) ref.Val { - if TypeType != other.Type() { - return ValOrErr(other, "no such overload") - } - return Bool(t.TypeName() == other.(ref.Type).TypeName()) + otherType, ok := other.(ref.Type) + return Bool(ok && t.TypeName() == otherType.TypeName()) } // HasTrait indicates whether the type supports the given trait. diff --git a/vendor/github.com/google/cel-go/common/types/uint.go b/vendor/github.com/google/cel-go/common/types/uint.go index a313d9171..ca266e045 100644 --- a/vendor/github.com/google/cel-go/common/types/uint.go +++ b/vendor/github.com/google/cel-go/common/types/uint.go @@ -55,33 +55,42 @@ const ( func (i Uint) Add(other ref.Val) ref.Val { otherUint, ok := other.(Uint) if !ok { - return ValOrErr(other, "no such overload") + return MaybeNoSuchOverloadErr(other) } - if otherUint > 0 && i > math.MaxUint64-otherUint { - return NewErr("unsigned integer overflow") + val, err := addUint64Checked(uint64(i), uint64(otherUint)) + if err != nil { + return wrapErr(err) } - return i + otherUint + return Uint(val) } // Compare implements traits.Comparer.Compare. func (i Uint) Compare(other ref.Val) ref.Val { - otherUint, ok := other.(Uint) - if !ok { - return ValOrErr(other, "no such overload") + switch ov := other.(type) { + case Double: + if math.IsNaN(float64(ov)) { + return NewErr("NaN values cannot be ordered") + } + return compareUintDouble(i, ov) + case Int: + return compareUintInt(i, ov) + case Uint: + return compareUint(i, ov) + default: + return MaybeNoSuchOverloadErr(other) } - if i < otherUint { - return IntNegOne - } - if i > otherUint { - return IntOne - } - return IntZero } // ConvertToNative implements ref.Val.ConvertToNative. func (i Uint) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { switch typeDesc.Kind() { - case reflect.Uint, reflect.Uint32, reflect.Uint64: + case reflect.Uint, reflect.Uint32: + v, err := uint64ToUint32Checked(uint64(i)) + if err != nil { + return 0, err + } + return reflect.ValueOf(v).Convert(typeDesc).Interface(), nil + case reflect.Uint64: return reflect.ValueOf(i).Convert(typeDesc).Interface(), nil case reflect.Ptr: switch typeDesc { @@ -97,15 +106,22 @@ func (i Uint) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { // since the conversion to floating point would result in truncation. return structpb.NewStringValue(strconv.FormatUint(uint64(i), 10)), nil case uint32WrapperType: - // Convert the value to a wrapperspb.UInt32Value (with truncation). - return wrapperspb.UInt32(uint32(i)), nil + // Convert the value to a wrapperspb.UInt32Value, error on overflow. + v, err := uint64ToUint32Checked(uint64(i)) + if err != nil { + return 0, err + } + return wrapperspb.UInt32(v), nil case uint64WrapperType: // Convert the value to a wrapperspb.UInt64Value. return wrapperspb.UInt64(uint64(i)), nil } switch typeDesc.Elem().Kind() { case reflect.Uint32: - v := uint32(i) + v, err := uint64ToUint32Checked(uint64(i)) + if err != nil { + return 0, err + } p := reflect.New(typeDesc.Elem()) p.Elem().Set(reflect.ValueOf(v).Convert(typeDesc.Elem())) return p.Interface(), nil @@ -131,10 +147,11 @@ func (i Uint) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { func (i Uint) ConvertToType(typeVal ref.Type) ref.Val { switch typeVal { case IntType: - if i > math.MaxInt64 { - return NewErr("range error converting %d to int", i) + v, err := uint64ToInt64Checked(uint64(i)) + if err != nil { + return wrapErr(err) } - return Int(i) + return Int(v) case UintType: return i case DoubleType: @@ -151,57 +168,69 @@ func (i Uint) ConvertToType(typeVal ref.Type) ref.Val { func (i Uint) Divide(other ref.Val) ref.Val { otherUint, ok := other.(Uint) if !ok { - return ValOrErr(other, "no such overload") + return MaybeNoSuchOverloadErr(other) } - if otherUint == uintZero { - return NewErr("divide by zero") + div, err := divideUint64Checked(uint64(i), uint64(otherUint)) + if err != nil { + return wrapErr(err) } - return i / otherUint + return Uint(div) } // Equal implements ref.Val.Equal. func (i Uint) Equal(other ref.Val) ref.Val { - otherUint, ok := other.(Uint) - if !ok { - return ValOrErr(other, "no such overload") + switch ov := other.(type) { + case Double: + if math.IsNaN(float64(ov)) { + return False + } + return Bool(compareUintDouble(i, ov) == 0) + case Int: + return Bool(compareUintInt(i, ov) == 0) + case Uint: + return Bool(i == ov) + default: + return False } - return Bool(i == otherUint) } // Modulo implements traits.Modder.Modulo. func (i Uint) Modulo(other ref.Val) ref.Val { otherUint, ok := other.(Uint) if !ok { - return ValOrErr(other, "no such overload") + return MaybeNoSuchOverloadErr(other) } - if otherUint == uintZero { - return NewErr("modulus by zero") + mod, err := moduloUint64Checked(uint64(i), uint64(otherUint)) + if err != nil { + return wrapErr(err) } - return i % otherUint + return Uint(mod) } // Multiply implements traits.Multiplier.Multiply. func (i Uint) Multiply(other ref.Val) ref.Val { otherUint, ok := other.(Uint) if !ok { - return ValOrErr(other, "no such overload") + return MaybeNoSuchOverloadErr(other) } - if otherUint != 0 && i > math.MaxUint64/otherUint { - return NewErr("unsigned integer overflow") + val, err := multiplyUint64Checked(uint64(i), uint64(otherUint)) + if err != nil { + return wrapErr(err) } - return i * otherUint + return Uint(val) } // Subtract implements traits.Subtractor.Subtract. func (i Uint) Subtract(subtrahend ref.Val) ref.Val { subtraUint, ok := subtrahend.(Uint) if !ok { - return ValOrErr(subtrahend, "no such overload") + return MaybeNoSuchOverloadErr(subtrahend) } - if subtraUint > i { - return NewErr("unsigned integer overflow") + val, err := subtractUint64Checked(uint64(i), uint64(subtraUint)) + if err != nil { + return wrapErr(err) } - return i - subtraUint + return Uint(val) } // Type implements ref.Val.Type. diff --git a/vendor/github.com/google/cel-go/common/types/unknown.go b/vendor/github.com/google/cel-go/common/types/unknown.go index a950920d6..95b47426f 100644 --- a/vendor/github.com/google/cel-go/common/types/unknown.go +++ b/vendor/github.com/google/cel-go/common/types/unknown.go @@ -34,12 +34,12 @@ func (u Unknown) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { return u.Value(), nil } -// ConvertToType implements ref.Val.ConvertToType. +// ConvertToType is an identity function since unknown values cannot be modified. func (u Unknown) ConvertToType(typeVal ref.Type) ref.Val { return u } -// Equal implements ref.Val.Equal. +// Equal is an identity function since unknown values cannot be modified. func (u Unknown) Equal(other ref.Val) ref.Val { return u } @@ -57,5 +57,10 @@ func (u Unknown) Value() interface{} { // IsUnknown returns whether the element ref.Type or ref.Val is equal to the // UnknownType singleton. func IsUnknown(val ref.Val) bool { - return val.Type() == UnknownType + switch val.(type) { + case Unknown: + return true + default: + return false + } } diff --git a/vendor/github.com/google/cel-go/common/types/util.go b/vendor/github.com/google/cel-go/common/types/util.go index 761c512d7..a8e9afa9e 100644 --- a/vendor/github.com/google/cel-go/common/types/util.go +++ b/vendor/github.com/google/cel-go/common/types/util.go @@ -18,10 +18,10 @@ import ( "github.com/google/cel-go/common/types/ref" ) -// IsUnknownOrError returns whether the input element ref.Val is an ErrType or UnknonwType. +// IsUnknownOrError returns whether the input element ref.Val is an ErrType or UnknownType. func IsUnknownOrError(val ref.Val) bool { - switch val.Type() { - case UnknownType, ErrType: + switch val.(type) { + case Unknown, *Err: return true } return false @@ -36,3 +36,13 @@ func IsPrimitiveType(val ref.Val) bool { } return false } + +// Equal returns whether the two ref.Value are heterogeneously equivalent. +func Equal(lhs ref.Val, rhs ref.Val) ref.Val { + lNull := lhs == NullValue + rNull := rhs == NullValue + if lNull || rNull { + return Bool(lNull == rNull) + } + return lhs.Equal(rhs) +} diff --git a/vendor/github.com/google/cel-go/interpreter/activation.go b/vendor/github.com/google/cel-go/interpreter/activation.go index 4f1315199..8686d4f04 100644 --- a/vendor/github.com/google/cel-go/interpreter/activation.go +++ b/vendor/github.com/google/cel-go/interpreter/activation.go @@ -35,13 +35,17 @@ type Activation interface { Parent() Activation } -// EmptyActivation returns a variable free activation. +// EmptyActivation returns a variable-free activation. func EmptyActivation() Activation { - // This call cannot fail. - a, _ := NewActivation(map[string]interface{}{}) - return a + return emptyActivation{} } +// emptyActivation is a variable-free activation. +type emptyActivation struct{} + +func (emptyActivation) ResolveName(string) (interface{}, bool) { return nil, false } +func (emptyActivation) Parent() Activation { return nil } + // NewActivation returns an activation based on a map-based binding where the map keys are // expected to be qualified names used with ResolveName calls. // diff --git a/vendor/github.com/google/cel-go/interpreter/attribute_patterns.go b/vendor/github.com/google/cel-go/interpreter/attribute_patterns.go index 3633255d2..b33f7f7fd 100644 --- a/vendor/github.com/google/cel-go/interpreter/attribute_patterns.go +++ b/vendor/github.com/google/cel-go/interpreter/attribute_patterns.go @@ -105,7 +105,7 @@ func (apat *AttributePattern) QualifierPatterns() []*AttributeQualifierPattern { return apat.qualifierPatterns } -// AttributeQualifierPattern holds a wilcard or valued qualifier pattern. +// AttributeQualifierPattern holds a wildcard or valued qualifier pattern. type AttributeQualifierPattern struct { wildcard bool value interface{} @@ -125,7 +125,7 @@ func (qpat *AttributeQualifierPattern) Matches(q Qualifier) bool { // type, is equal to the value held in the Qualifier. This interface is used by the // AttributeQualifierPattern to determine pattern matches for non-wildcard qualifier patterns. // -// Note: Attribute values are also Qualifier values; however, Attriutes are resolved before +// Note: Attribute values are also Qualifier values; however, Attributes are resolved before // qualification happens. This is an implementation detail, but one relevant to why the Attribute // types do not surface in the list of implementations. // @@ -157,14 +157,23 @@ func (q *stringQualifier) QualifierValueEquals(value interface{}) bool { // QualifierValueEquals implementation for int qualifiers. func (q *intQualifier) QualifierValueEquals(value interface{}) bool { - ival, ok := value.(int64) - return ok && q.value == ival + return numericValueEquals(value, q.celValue) } // QualifierValueEquals implementation for uint qualifiers. func (q *uintQualifier) QualifierValueEquals(value interface{}) bool { - uval, ok := value.(uint64) - return ok && q.value == uval + return numericValueEquals(value, q.celValue) +} + +// QualifierValueEquals implementation for double qualifiers. +func (q *doubleQualifier) QualifierValueEquals(value interface{}) bool { + return numericValueEquals(value, q.celValue) +} + +// numericValueEquals uses CEL equality to determine whether two number values are +func numericValueEquals(value interface{}, celValue ref.Val) bool { + val := types.DefaultTypeAdapter.NativeToValue(value) + return celValue.Equal(val) == types.True } // NewPartialAttributeFactory returns an AttributeFactory implementation capable of performing @@ -197,7 +206,7 @@ func (fac *partialAttributeFactory) AbsoluteAttribute(id int64, names ...string) } // MaybeAttribute implementation of the AttributeFactory interface which ensure that the set of -// 'maybe' NamespacedAttribute values are produced using the PartialAttributeFactory rather than +// 'maybe' NamespacedAttribute values are produced using the partialAttributeFactory rather than // the base AttributeFactory implementation. func (fac *partialAttributeFactory) MaybeAttribute(id int64, name string) Attribute { return &maybeAttribute{ @@ -348,7 +357,8 @@ func (m *attributeMatcher) Resolve(vars Activation) (interface{}, error) { // the standard Resolve logic applies. func (m *attributeMatcher) TryResolve(vars Activation) (interface{}, bool, error) { id := m.NamespacedAttribute.ID() - partial, isPartial := vars.(PartialActivation) + // Bug in how partial activation is resolved, should search parents as well. + partial, isPartial := toPartialActivation(vars) if isPartial { unk, err := m.fac.matchesUnknownPatterns( partial, @@ -381,3 +391,14 @@ func (m *attributeMatcher) Qualify(vars Activation, obj interface{}) (interface{ } return qual.Qualify(vars, obj) } + +func toPartialActivation(vars Activation) (PartialActivation, bool) { + pv, ok := vars.(PartialActivation) + if ok { + return pv, true + } + if vars.Parent() != nil { + return toPartialActivation(vars.Parent()) + } + return nil, false +} diff --git a/vendor/github.com/google/cel-go/interpreter/attributes.go b/vendor/github.com/google/cel-go/interpreter/attributes.go index e101c669b..4f1772ea3 100644 --- a/vendor/github.com/google/cel-go/interpreter/attributes.go +++ b/vendor/github.com/google/cel-go/interpreter/attributes.go @@ -15,7 +15,6 @@ package interpreter import ( - "errors" "fmt" "math" @@ -487,9 +486,7 @@ func (a *maybeAttribute) AddQualifier(qual Qualifier) (Attribute, error) { } } // Next, ensure the most specific variable / type reference is searched first. - a.attrs = append([]NamespacedAttribute{ - a.fac.AbsoluteAttribute(qual.ID(), augmentedNames...), - }, a.attrs...) + a.attrs = append([]NamespacedAttribute{a.fac.AbsoluteAttribute(qual.ID(), augmentedNames...)}, a.attrs...) return a, nil } @@ -590,7 +587,7 @@ func (a *relativeAttribute) Resolve(vars Activation) (interface{}, error) { if types.IsUnknown(v) { return v, nil } - // Next, qualify it. Qualification handles unkonwns as well, so there's no need to recheck. + // Next, qualify it. Qualification handles unknowns as well, so there's no need to recheck. var err error var obj interface{} = v for _, qual := range a.qualifiers { @@ -628,6 +625,10 @@ func newQualifier(adapter ref.TypeAdapter, id int64, v interface{}) (Qualifier, qual = &uintQualifier{id: id, value: val, celValue: types.Uint(val), adapter: adapter} case bool: qual = &boolQualifier{id: id, value: val, celValue: types.Bool(val), adapter: adapter} + case float32: + qual = &doubleQualifier{id: id, value: float64(val), celValue: types.Double(val), adapter: adapter} + case float64: + qual = &doubleQualifier{id: id, value: val, celValue: types.Double(val), adapter: adapter} case types.String: qual = &stringQualifier{id: id, value: string(val), celValue: val, adapter: adapter} case types.Int: @@ -636,6 +637,8 @@ func newQualifier(adapter ref.TypeAdapter, id int64, v interface{}) (Qualifier, qual = &uintQualifier{id: id, value: uint64(val), celValue: val, adapter: adapter} case types.Bool: qual = &boolQualifier{id: id, value: bool(val), celValue: val, adapter: adapter} + case types.Double: + qual = &doubleQualifier{id: id, value: float64(val), celValue: val, adapter: adapter} default: return nil, fmt.Errorf("invalid qualifier type: %T", v) } @@ -714,9 +717,6 @@ func (q *stringQualifier) Qualify(vars Activation, obj interface{}) (interface{} if err != nil { return nil, err } - if types.IsUnknown(elem) { - return elem, nil - } return elem, nil } if isMap && !isKey { @@ -829,9 +829,6 @@ func (q *intQualifier) Qualify(vars Activation, obj interface{}) (interface{}, e if err != nil { return nil, err } - if types.IsUnknown(elem) { - return elem, nil - } return elem, nil } if isMap && !isKey { @@ -891,9 +888,6 @@ func (q *uintQualifier) Qualify(vars Activation, obj interface{}) (interface{}, if err != nil { return nil, err } - if types.IsUnknown(elem) { - return elem, nil - } return elem, nil } if isMap && !isKey { @@ -942,9 +936,6 @@ func (q *boolQualifier) Qualify(vars Activation, obj interface{}) (interface{}, if err != nil { return nil, err } - if types.IsUnknown(elem) { - return elem, nil - } return elem, nil } if !isKey { @@ -996,6 +987,37 @@ func (q *fieldQualifier) Cost() (min, max int64) { return 0, 0 } +// doubleQualifier qualifies a CEL object, map, or list using a double value. +// +// This qualifier is used for working with dynamic data like JSON or protobuf.Any where the value +// type may not be known ahead of time and may not conform to the standard types supported as valid +// protobuf map key types. +type doubleQualifier struct { + id int64 + value float64 + celValue ref.Val + adapter ref.TypeAdapter +} + +// ID is an implementation of the Qualifier interface method. +func (q *doubleQualifier) ID() int64 { + return q.id +} + +// Qualify implements the Qualifier interface method. +func (q *doubleQualifier) Qualify(vars Activation, obj interface{}) (interface{}, error) { + switch o := obj.(type) { + case types.Unknown: + return o, nil + default: + elem, err := refResolve(q.adapter, q.celValue, obj) + if err != nil { + return nil, err + } + return elem, nil + } +} + // refResolve attempts to convert the value to a CEL value and then uses reflection methods // to try and resolve the qualifier. func refResolve(adapter ref.TypeAdapter, idx ref.Val, obj interface{}) (ref.Val, error) { @@ -1006,9 +1028,6 @@ func refResolve(adapter ref.TypeAdapter, idx ref.Val, obj interface{}) (ref.Val, if !found { return nil, fmt.Errorf("no such key: %v", idx) } - if types.IsError(elem) { - return nil, elem.(*types.Err) - } return elem, nil } indexer, isIndexer := celVal.(traits.Indexer) @@ -1028,5 +1047,5 @@ func refResolve(adapter ref.TypeAdapter, idx ref.Val, obj interface{}) (ref.Val, if types.IsError(celVal) { return nil, celVal.(*types.Err) } - return nil, errors.New("no such overload") + return nil, fmt.Errorf("no such key: %v", idx) } diff --git a/vendor/github.com/google/cel-go/interpreter/coster.go b/vendor/github.com/google/cel-go/interpreter/coster.go index 15cb6bc04..ac573d574 100644 --- a/vendor/github.com/google/cel-go/interpreter/coster.go +++ b/vendor/github.com/google/cel-go/interpreter/coster.go @@ -16,7 +16,11 @@ package interpreter import "math" +// TODO: remove Coster. + // Coster calculates the heuristic cost incurred during evaluation. +// Deprecated: Please migrate cel.EstimateCost, it supports length estimates for input data and cost estimates for +// extension functions. type Coster interface { Cost() (min, max int64) } diff --git a/vendor/github.com/google/cel-go/interpreter/decorators.go b/vendor/github.com/google/cel-go/interpreter/decorators.go index 23a7f695b..bdbbad43e 100644 --- a/vendor/github.com/google/cel-go/interpreter/decorators.go +++ b/vendor/github.com/google/cel-go/interpreter/decorators.go @@ -25,11 +25,8 @@ import ( // Interpretable expression nodes at construction time. type InterpretableDecorator func(Interpretable) (Interpretable, error) -// evalObserver is a functional interface that accepts an expression id and an observed value. -type evalObserver func(int64, ref.Val) - // decObserveEval records evaluation state into an EvalState object. -func decObserveEval(observer evalObserver) InterpretableDecorator { +func decObserveEval(observer EvalObserver) InterpretableDecorator { return func(i Interpretable) (Interpretable, error) { switch inst := i.(type) { case *evalWatch, *evalWatchAttr, *evalWatchConst: @@ -54,6 +51,19 @@ func decObserveEval(observer evalObserver) InterpretableDecorator { } } +// decInterruptFolds creates an intepretable decorator which marks comprehensions as interruptable +// where the interrupt state is communicated via a hidden variable on the Activation. +func decInterruptFolds() InterpretableDecorator { + return func(i Interpretable) (Interpretable, error) { + fold, ok := i.(*evalFold) + if !ok { + return i, nil + } + fold.interruptable = true + return fold, nil + } +} + // decDisableShortcircuits ensures that all branches of an expression will be evaluated, no short-circuiting. func decDisableShortcircuits() InterpretableDecorator { return func(i Interpretable) (Interpretable, error) { @@ -71,16 +81,8 @@ func decDisableShortcircuits() InterpretableDecorator { rhs: expr.rhs, }, nil case *evalFold: - return &evalExhaustiveFold{ - id: expr.id, - accu: expr.accu, - accuVar: expr.accuVar, - iterRange: expr.iterRange, - iterVar: expr.iterVar, - cond: expr.cond, - step: expr.step, - result: expr.result, - }, nil + expr.exhaustive = true + return expr, nil case InterpretableAttribute: cond, isCond := expr.Attr().(*conditionalAttribute) if isCond { @@ -96,7 +98,7 @@ func decDisableShortcircuits() InterpretableDecorator { } // decOptimize optimizes the program plan by looking for common evaluation patterns and -// conditionally precomputating the result. +// conditionally precomputing the result. // - build list and map values with constant elements. // - convert 'in' operations to set membership tests if possible. func decOptimize() InterpretableDecorator { @@ -118,6 +120,48 @@ func decOptimize() InterpretableDecorator { } } +// decRegexOptimizer compiles regex pattern string constants. +func decRegexOptimizer(regexOptimizations ...*RegexOptimization) InterpretableDecorator { + functionMatchMap := make(map[string]*RegexOptimization) + overloadMatchMap := make(map[string]*RegexOptimization) + for _, m := range regexOptimizations { + functionMatchMap[m.Function] = m + if m.OverloadID != "" { + overloadMatchMap[m.OverloadID] = m + } + } + + return func(i Interpretable) (Interpretable, error) { + call, ok := i.(InterpretableCall) + if !ok { + return i, nil + } + + var matcher *RegexOptimization + var found bool + if call.OverloadID() != "" { + matcher, found = overloadMatchMap[call.OverloadID()] + } + if !found { + matcher, found = functionMatchMap[call.Function()] + } + if !found || matcher.RegexIndex >= len(call.Args()) { + return i, nil + } + args := call.Args() + regexArg := args[matcher.RegexIndex] + regexStr, isConst := regexArg.(InterpretableConst) + if !isConst { + return i, nil + } + pattern, ok := regexStr.Value().(types.String) + if !ok { + return i, nil + } + return matcher.Factory(call, string(pattern)) + } +} + func maybeOptimizeConstUnary(i Interpretable, call InterpretableCall) (Interpretable, error) { args := call.Args() if len(args) != 1 { @@ -177,7 +221,6 @@ func maybeOptimizeSetMembership(i Interpretable, inlist InterpretableCall) (Inte return NewConstValue(inlist.ID(), types.False), nil } it := list.Iterator() - var typ ref.Type valueSet := make(map[ref.Val]ref.Val) for it.HasNext() == types.True { elem := it.Next() @@ -185,17 +228,42 @@ func maybeOptimizeSetMembership(i Interpretable, inlist InterpretableCall) (Inte // Note, non-primitive type are not yet supported. return i, nil } - if typ == nil { - typ = elem.Type() - } else if typ.TypeName() != elem.Type().TypeName() { - return i, nil - } valueSet[elem] = types.True + switch ev := elem.(type) { + case types.Double: + iv := ev.ConvertToType(types.IntType) + // Ensure that only lossless conversions are added to the set + if !types.IsError(iv) && iv.Equal(ev) == types.True { + valueSet[iv] = types.True + } + // Ensure that only lossless conversions are added to the set + uv := ev.ConvertToType(types.UintType) + if !types.IsError(uv) && uv.Equal(ev) == types.True { + valueSet[uv] = types.True + } + case types.Int: + dv := ev.ConvertToType(types.DoubleType) + if !types.IsError(dv) { + valueSet[dv] = types.True + } + uv := ev.ConvertToType(types.UintType) + if !types.IsError(uv) { + valueSet[uv] = types.True + } + case types.Uint: + dv := ev.ConvertToType(types.DoubleType) + if !types.IsError(dv) { + valueSet[dv] = types.True + } + iv := ev.ConvertToType(types.IntType) + if !types.IsError(iv) { + valueSet[iv] = types.True + } + } } return &evalSetMembership{ - inst: inlist, - arg: lhs, - argTypeName: typ.TypeName(), - valueSet: valueSet, + inst: inlist, + arg: lhs, + valueSet: valueSet, }, nil } diff --git a/vendor/github.com/google/cel-go/interpreter/functions/standard.go b/vendor/github.com/google/cel-go/interpreter/functions/standard.go index c8767bc17..73e936114 100644 --- a/vendor/github.com/google/cel-go/interpreter/functions/standard.go +++ b/vendor/github.com/google/cel-go/interpreter/functions/standard.go @@ -100,8 +100,6 @@ func StandardOverloads() []*Overload { return cmp }}, - // TODO: Verify overflow, NaN, underflow cases for numeric values. - // Add operator {Operator: operators.Add, OperandTrait: traits.AdderType, diff --git a/vendor/github.com/google/cel-go/interpreter/interpretable.go b/vendor/github.com/google/cel-go/interpreter/interpretable.go index 28af6d44b..43111f680 100644 --- a/vendor/github.com/google/cel-go/interpreter/interpretable.go +++ b/vendor/github.com/google/cel-go/interpreter/interpretable.go @@ -88,6 +88,18 @@ type InterpretableCall interface { Args() []Interpretable } +// InterpretableConstructor interface for inspecting Interpretable instructions that initialize a list, map +// or struct. +type InterpretableConstructor interface { + Interpretable + + // InitVals returns all the list elements, map key and values or struct field values. + InitVals() []Interpretable + + // Type returns the type constructed. + Type() ref.Type +} + // Core Interpretable implementations used during the program planning phase. type evalTestOnly struct { @@ -298,7 +310,13 @@ func (eq *evalEq) ID() int64 { func (eq *evalEq) Eval(ctx Activation) ref.Val { lVal := eq.lhs.Eval(ctx) rVal := eq.rhs.Eval(ctx) - return lVal.Equal(rVal) + if types.IsUnknownOrError(lVal) { + return lVal + } + if types.IsUnknownOrError(rVal) { + return rVal + } + return types.Equal(lVal, rVal) } // Cost implements the Coster interface method. @@ -336,12 +354,13 @@ func (ne *evalNe) ID() int64 { func (ne *evalNe) Eval(ctx Activation) ref.Val { lVal := ne.lhs.Eval(ctx) rVal := ne.rhs.Eval(ctx) - eqVal := lVal.Equal(rVal) - eqBool, ok := eqVal.(types.Bool) - if !ok { - return types.ValOrErr(eqVal, "no such overload: _!=_") + if types.IsUnknownOrError(lVal) { + return lVal } - return !eqBool + if types.IsUnknownOrError(rVal) { + return rVal + } + return types.Bool(types.Equal(lVal, rVal) != types.True) } // Cost implements the Coster interface method. @@ -526,6 +545,17 @@ type evalVarArgs struct { impl functions.FunctionOp } +// NewCall creates a new call Interpretable. +func NewCall(id int64, function, overload string, args []Interpretable, impl functions.FunctionOp) InterpretableCall { + return &evalVarArgs{ + id: id, + function: function, + overload: overload, + args: args, + impl: impl, + } +} + // ID implements the Interpretable interface method. func (fn *evalVarArgs) ID() int64 { return fn.id @@ -603,6 +633,14 @@ func (l *evalList) Eval(ctx Activation) ref.Val { return l.adapter.NativeToValue(elemVals) } +func (l *evalList) InitVals() []Interpretable { + return l.elems +} + +func (l *evalList) Type() ref.Type { + return types.ListType +} + // Cost implements the Coster interface method. func (l *evalList) Cost() (min, max int64) { return sumOfCost(l.elems) @@ -638,6 +676,26 @@ func (m *evalMap) Eval(ctx Activation) ref.Val { return m.adapter.NativeToValue(entries) } +func (m *evalMap) InitVals() []Interpretable { + if len(m.keys) != len(m.vals) { + return nil + } + result := make([]Interpretable, len(m.keys)+len(m.vals)) + idx := 0 + for i, k := range m.keys { + v := m.vals[i] + result[idx] = k + idx++ + result[idx] = v + idx++ + } + return result +} + +func (m *evalMap) Type() ref.Type { + return types.MapType +} + // Cost implements the Coster interface method. func (m *evalMap) Cost() (min, max int64) { kMin, kMax := sumOfCost(m.keys) @@ -672,6 +730,14 @@ func (o *evalObj) Eval(ctx Activation) ref.Val { return o.provider.NewValue(o.typeName, fieldVals) } +func (o *evalObj) InitVals() []Interpretable { + return o.vals +} + +func (o *evalObj) Type() ref.Type { + return types.NewObjectTypeValue(o.typeName) +} + // Cost implements the Coster interface method. func (o *evalObj) Cost() (min, max int64) { return sumOfCost(o.vals) @@ -688,14 +754,17 @@ func sumOfCost(interps []Interpretable) (min, max int64) { } type evalFold struct { - id int64 - accuVar string - iterVar string - iterRange Interpretable - accu Interpretable - cond Interpretable - step Interpretable - result Interpretable + id int64 + accuVar string + iterVar string + iterRange Interpretable + accu Interpretable + cond Interpretable + step Interpretable + result Interpretable + adapter ref.TypeAdapter + exhaustive bool + interruptable bool } // ID implements the Interpretable interface method. @@ -714,9 +783,19 @@ func (fold *evalFold) Eval(ctx Activation) ref.Val { accuCtx.parent = ctx accuCtx.name = fold.accuVar accuCtx.val = fold.accu.Eval(ctx) + // If the accumulator starts as an empty list, then the comprehension will build a list + // so create a mutable list to optimize the cost of the inner loop. + l, ok := accuCtx.val.(traits.Lister) + buildingList := false + if !fold.exhaustive && ok && l.Size() == types.IntZero { + buildingList = true + accuCtx.val = types.NewMutableList(fold.adapter) + } iterCtx := varActivationPool.Get().(*varActivation) iterCtx.parent = accuCtx iterCtx.name = fold.iterVar + + interrupted := false it := foldRange.(traits.Iterable).Iterator() for it.HasNext() == types.True { // Modify the iter var in the fold activation. @@ -725,17 +804,31 @@ func (fold *evalFold) Eval(ctx Activation) ref.Val { // Evaluate the condition, terminate the loop if false. cond := fold.cond.Eval(iterCtx) condBool, ok := cond.(types.Bool) - if !types.IsUnknown(cond) && ok && condBool != types.True { + if !fold.exhaustive && ok && condBool != types.True { break } - - // Evalute the evaluation step into accu var. + // Evaluate the evaluation step into accu var. accuCtx.val = fold.step.Eval(iterCtx) + if fold.interruptable { + if stop, found := ctx.ResolveName("#interrupted"); found && stop == true { + interrupted = true + break + } + } } + varActivationPool.Put(iterCtx) + if interrupted { + varActivationPool.Put(accuCtx) + return types.NewErr("operation interrupted") + } + // Compute the result. res := fold.result.Eval(accuCtx) - varActivationPool.Put(iterCtx) varActivationPool.Put(accuCtx) + // Convert a mutable list to an immutable one, if the comprehension has generated a list as a result. + if !types.IsUnknownOrError(res) && buildingList { + res = res.(traits.MutableLister).ToImmutableList() + } return res } @@ -760,6 +853,10 @@ func (fold *evalFold) Cost() (min, max int64) { cMin, cMax := estimateCost(fold.cond) sMin, sMax := estimateCost(fold.step) rMin, rMax := estimateCost(fold.result) + if fold.exhaustive { + cMin = cMin * rangeCnt + sMin = sMin * rangeCnt + } // The cond and step costs are multiplied by size(iterRange). The minimum possible cost incurs // when the evaluation result can be determined by the first iteration. @@ -767,16 +864,15 @@ func (fold *evalFold) Cost() (min, max int64) { iMax + aMax + cMax*rangeCnt + sMax*rangeCnt + rMax } -// Optional Intepretable implementations that specialize, subsume, or extend the core evaluation +// Optional Interpretable implementations that specialize, subsume, or extend the core evaluation // plan via decorators. // evalSetMembership is an Interpretable implementation which tests whether an input value // exists within the set of map keys used to model a set. type evalSetMembership struct { - inst Interpretable - arg Interpretable - argTypeName string - valueSet map[ref.Val]ref.Val + inst Interpretable + arg Interpretable + valueSet map[ref.Val]ref.Val } // ID implements the Interpretable interface method. @@ -787,9 +883,6 @@ func (e *evalSetMembership) ID() int64 { // Eval implements the Interpretable interface method. func (e *evalSetMembership) Eval(ctx Activation) ref.Val { val := e.arg.Eval(ctx) - if val.Type().TypeName() != e.argTypeName { - return types.ValOrErr(val, "no such overload") - } if ret, found := e.valueSet[val]; found { return ret } @@ -805,13 +898,13 @@ func (e *evalSetMembership) Cost() (min, max int64) { // expression so that it may observe the computed value and send it to an observer. type evalWatch struct { Interpretable - observer evalObserver + observer EvalObserver } // Eval implements the Interpretable interface method. func (e *evalWatch) Eval(ctx Activation) ref.Val { val := e.Interpretable.Eval(ctx) - e.observer(e.ID(), val) + e.observer(e.ID(), e.Interpretable, val) return val } @@ -826,7 +919,7 @@ func (e *evalWatch) Cost() (min, max int64) { // must implement the instAttr interface by proxy. type evalWatchAttr struct { InterpretableAttribute - observer evalObserver + observer EvalObserver } // AddQualifier creates a wrapper over the incoming qualifier which observes the qualification @@ -850,11 +943,23 @@ func (e *evalWatchAttr) AddQualifier(q Qualifier) (Attribute, error) { return e, err } +// Cost implements the Coster interface method. +func (e *evalWatchAttr) Cost() (min, max int64) { + return estimateCost(e.InterpretableAttribute) +} + +// Eval implements the Interpretable interface method. +func (e *evalWatchAttr) Eval(vars Activation) ref.Val { + val := e.InterpretableAttribute.Eval(vars) + e.observer(e.ID(), e.InterpretableAttribute, val) + return val +} + // evalWatchConstQual observes the qualification of an object using a constant boolean, int, // string, or uint. type evalWatchConstQual struct { ConstantQualifier - observer evalObserver + observer EvalObserver adapter ref.TypeAdapter } @@ -872,11 +977,11 @@ func (e *evalWatchConstQual) Qualify(vars Activation, obj interface{}) (interfac } else { val = e.adapter.NativeToValue(out) } - e.observer(e.ID(), val) + e.observer(e.ID(), e.ConstantQualifier, val) return out, err } -// QualifierValueEquals tests whether the incoming value is equal to the qualificying constant. +// QualifierValueEquals tests whether the incoming value is equal to the qualifying constant. func (e *evalWatchConstQual) QualifierValueEquals(value interface{}) bool { qve, ok := e.ConstantQualifier.(qualifierValueEquator) return ok && qve.QualifierValueEquals(value) @@ -885,7 +990,7 @@ func (e *evalWatchConstQual) QualifierValueEquals(value interface{}) bool { // evalWatchQual observes the qualification of an object by a value computed at runtime. type evalWatchQual struct { Qualifier - observer evalObserver + observer EvalObserver adapter ref.TypeAdapter } @@ -903,32 +1008,20 @@ func (e *evalWatchQual) Qualify(vars Activation, obj interface{}) (interface{}, } else { val = e.adapter.NativeToValue(out) } - e.observer(e.ID(), val) + e.observer(e.ID(), e.Qualifier, val) return out, err } -// Cost implements the Coster interface method. -func (e *evalWatchAttr) Cost() (min, max int64) { - return estimateCost(e.InterpretableAttribute) -} - -// Eval implements the Interpretable interface method. -func (e *evalWatchAttr) Eval(vars Activation) ref.Val { - val := e.InterpretableAttribute.Eval(vars) - e.observer(e.ID(), val) - return val -} - // evalWatchConst describes a watcher of an instConst Interpretable. type evalWatchConst struct { InterpretableConst - observer evalObserver + observer EvalObserver } // Eval implements the Interpretable interface method. func (e *evalWatchConst) Eval(vars Activation) ref.Val { val := e.Value() - e.observer(e.ID(), val) + e.observer(e.ID(), e.InterpretableConst, val) return val } @@ -1074,83 +1167,6 @@ func (cond *evalExhaustiveConditional) Cost() (min, max int64) { return cond.attr.Cost() } -// evalExhaustiveFold is like evalFold, but does not short-circuit argument evaluation. -type evalExhaustiveFold struct { - id int64 - accuVar string - iterVar string - iterRange Interpretable - accu Interpretable - cond Interpretable - step Interpretable - result Interpretable -} - -// ID implements the Interpretable interface method. -func (fold *evalExhaustiveFold) ID() int64 { - return fold.id -} - -// Eval implements the Interpretable interface method. -func (fold *evalExhaustiveFold) Eval(ctx Activation) ref.Val { - foldRange := fold.iterRange.Eval(ctx) - if !foldRange.Type().HasTrait(traits.IterableType) { - return types.ValOrErr(foldRange, "got '%T', expected iterable type", foldRange) - } - // Configure the fold activation with the accumulator initial value. - accuCtx := varActivationPool.Get().(*varActivation) - accuCtx.parent = ctx - accuCtx.name = fold.accuVar - accuCtx.val = fold.accu.Eval(ctx) - iterCtx := varActivationPool.Get().(*varActivation) - iterCtx.parent = accuCtx - iterCtx.name = fold.iterVar - it := foldRange.(traits.Iterable).Iterator() - for it.HasNext() == types.True { - // Modify the iter var in the fold activation. - iterCtx.val = it.Next() - - // Evaluate the condition, but don't terminate the loop as this is exhaustive eval! - fold.cond.Eval(iterCtx) - - // Evalute the evaluation step into accu var. - accuCtx.val = fold.step.Eval(iterCtx) - } - // Compute the result. - res := fold.result.Eval(accuCtx) - varActivationPool.Put(iterCtx) - varActivationPool.Put(accuCtx) - return res -} - -// Cost implements the Coster interface method. -func (fold *evalExhaustiveFold) Cost() (min, max int64) { - // Compute the cost for evaluating iterRange. - iMin, iMax := estimateCost(fold.iterRange) - - // Compute the size of iterRange. If the size depends on the input, return the maximum possible - // cost range. - foldRange := fold.iterRange.Eval(EmptyActivation()) - if !foldRange.Type().HasTrait(traits.IterableType) { - return 0, math.MaxInt64 - } - var rangeCnt int64 - it := foldRange.(traits.Iterable).Iterator() - for it.HasNext() == types.True { - it.Next() - rangeCnt++ - } - - aMin, aMax := estimateCost(fold.accu) - cMin, cMax := estimateCost(fold.cond) - sMin, sMax := estimateCost(fold.step) - rMin, rMax := estimateCost(fold.result) - - // The cond and step costs are multiplied by size(iterRange). - return iMin + aMin + cMin*rangeCnt + sMin*rangeCnt + rMin, - iMax + aMax + cMax*rangeCnt + sMax*rangeCnt + rMax -} - // evalAttr evaluates an Attribute value. type evalAttr struct { adapter ref.TypeAdapter diff --git a/vendor/github.com/google/cel-go/interpreter/interpreter.go b/vendor/github.com/google/cel-go/interpreter/interpreter.go index 6ffc41efe..b3fd14f8b 100644 --- a/vendor/github.com/google/cel-go/interpreter/interpreter.go +++ b/vendor/github.com/google/cel-go/interpreter/interpreter.go @@ -38,15 +38,67 @@ type Interpreter interface { decorators ...InterpretableDecorator) (Interpretable, error) } +// EvalObserver is a functional interface that accepts an expression id and an observed value. +// The id identifies the expression that was evaluated, the programStep is the Interpretable or Qualifier that +// was evaluated and value is the result of the evaluation. +type EvalObserver func(id int64, programStep interface{}, value ref.Val) + +// Observe constructs a decorator that calls all the provided observers in order after evaluating each Interpretable +// or Qualifier during program evaluation. +func Observe(observers ...EvalObserver) InterpretableDecorator { + if len(observers) == 1 { + return decObserveEval(observers[0]) + } + observeFn := func(id int64, programStep interface{}, val ref.Val) { + for _, observer := range observers { + observer(id, programStep, val) + } + } + return decObserveEval(observeFn) +} + +// EvalCancelledError represents a cancelled program evaluation operation. +type EvalCancelledError struct { + Message string + // Type identifies the cause of the cancellation. + Cause CancellationCause +} + +func (e EvalCancelledError) Error() string { + return e.Message +} + +// CancellationCause enumerates the ways a program evaluation operation can be cancelled. +type CancellationCause int + +const ( + // ContextCancelled indicates that the operation was cancelled in response to a Golang context cancellation. + ContextCancelled CancellationCause = iota + + // CostLimitExceeded indicates that the operation was cancelled in response to the actual cost limit being + // exceeded. + CostLimitExceeded +) + +// TODO: Replace all usages of TrackState with EvalStateObserver + // TrackState decorates each expression node with an observer which records the value // associated with the given expression id. EvalState must be provided to the decorator. // This decorator is not thread-safe, and the EvalState must be reset between Eval() // calls. +// DEPRECATED: Please use EvalStateObserver instead. It composes gracefully with additional observers. func TrackState(state EvalState) InterpretableDecorator { - observer := func(id int64, val ref.Val) { + return Observe(EvalStateObserver(state)) +} + +// EvalStateObserver provides an observer which records the value +// associated with the given expression id. EvalState must be provided to the observer. +// This decorator is not thread-safe, and the EvalState must be reset between Eval() +// calls. +func EvalStateObserver(state EvalState) EvalObserver { + return func(id int64, programStep interface{}, val ref.Val) { state.SetValue(id, val) } - return decObserveEval(observer) } // ExhaustiveEval replaces operations that short-circuit with versions that evaluate @@ -54,25 +106,53 @@ func TrackState(state EvalState) InterpretableDecorator { // insight into the evaluation state of the entire expression. EvalState must be // provided to the decorator. This decorator is not thread-safe, and the EvalState // must be reset between Eval() calls. -func ExhaustiveEval(state EvalState) InterpretableDecorator { +func ExhaustiveEval() InterpretableDecorator { ex := decDisableShortcircuits() - obs := TrackState(state) return func(i Interpretable) (Interpretable, error) { - var err error - i, err = ex(i) - if err != nil { - return nil, err - } - return obs(i) + return ex(i) } } +// InterruptableEval annotates comprehension loops with information that indicates they +// should check the `#interrupted` state within a custom Activation. +// +// The custom activation is currently managed higher up in the stack within the 'cel' package +// and should not require any custom support on behalf of callers. +func InterruptableEval() InterpretableDecorator { + return decInterruptFolds() +} + // Optimize will pre-compute operations such as list and map construction and optimize // call arguments to set membership tests. The set of optimizations will increase over time. func Optimize() InterpretableDecorator { return decOptimize() } +// RegexOptimization provides a way to replace an InterpretableCall for a regex function when the +// RegexIndex argument is a string constant. Typically, the Factory would compile the regex pattern at +// RegexIndex and report any errors (at program creation time) and then use the compiled regex for +// all regex function invocations. +type RegexOptimization struct { + // Function is the name of the function to optimize. + Function string + // OverloadID is the ID of the overload to optimize. + OverloadID string + // RegexIndex is the index position of the regex pattern argument. Only calls to the function where this argument is + // a string constant will be delegated to this optimizer. + RegexIndex int + // Factory constructs a replacement InterpretableCall node that optimizes the regex function call. Factory is + // provided with the unoptimized regex call and the string constant at the RegexIndex argument. + // The Factory may compile the regex for use across all invocations of the call, return any errors and + // return an interpreter.NewCall with the desired regex optimized function impl. + Factory func(call InterpretableCall, regexPattern string) (InterpretableCall, error) +} + +// CompileRegexConstants compiles regex pattern string constants at program creation time and reports any regex pattern +// compile errors. +func CompileRegexConstants(regexOptimizations ...*RegexOptimization) InterpretableDecorator { + return decRegexOptimizer(regexOptimizations...) +} + type exprInterpreter struct { dispatcher Dispatcher container *containers.Container @@ -82,7 +162,7 @@ type exprInterpreter struct { } // NewInterpreter builds an Interpreter from a Dispatcher and TypeProvider which will be used -// throughout the Eval of all Interpretable instances gerenated from it. +// throughout the Eval of all Interpretable instances generated from it. func NewInterpreter(dispatcher Dispatcher, container *containers.Container, provider ref.TypeProvider, diff --git a/vendor/github.com/google/cel-go/interpreter/optimizations.go b/vendor/github.com/google/cel-go/interpreter/optimizations.go new file mode 100644 index 000000000..2fc87e693 --- /dev/null +++ b/vendor/github.com/google/cel-go/interpreter/optimizations.go @@ -0,0 +1,46 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package interpreter + +import ( + "regexp" + + "github.com/google/cel-go/common/types" + "github.com/google/cel-go/common/types/ref" +) + +// MatchesRegexOptimization optimizes the 'matches' standard library function by compiling the regex pattern and +// reporting any compilation errors at program creation time, and using the compiled regex pattern for all function +// call invocations. +var MatchesRegexOptimization = &RegexOptimization{ + Function: "matches", + RegexIndex: 1, + Factory: func(call InterpretableCall, regexPattern string) (InterpretableCall, error) { + compiledRegex, err := regexp.Compile(regexPattern) + if err != nil { + return nil, err + } + return NewCall(call.ID(), call.Function(), call.OverloadID(), call.Args(), func(values ...ref.Val) ref.Val { + if len(values) != 2 { + return types.NoSuchOverloadErr() + } + in, ok := values[0].Value().(string) + if !ok { + return types.NoSuchOverloadErr() + } + return types.Bool(compiledRegex.MatchString(in)) + }), nil + }, +} diff --git a/vendor/github.com/google/cel-go/interpreter/planner.go b/vendor/github.com/google/cel-go/interpreter/planner.go index acfe31e6f..4a2d5b9d8 100644 --- a/vendor/github.com/google/cel-go/interpreter/planner.go +++ b/vendor/github.com/google/cel-go/interpreter/planner.go @@ -77,7 +77,7 @@ func newUncheckedPlanner(disp Dispatcher, } } -// planner is an implementatio of the interpretablePlanner interface. +// planner is an implementation of the interpretablePlanner interface. type planner struct { disp Dispatcher provider ref.TypeProvider @@ -617,6 +617,7 @@ func (p *planner) planComprehension(expr *exprpb.Expr) (Interpretable, error) { cond: cond, step: step, result: result, + adapter: p.adapter, }, nil } @@ -633,23 +634,23 @@ func (p *planner) planConst(expr *exprpb.Expr) (Interpretable, error) { func (p *planner) constValue(c *exprpb.Constant) (ref.Val, error) { switch c.ConstantKind.(type) { case *exprpb.Constant_BoolValue: - return types.Bool(c.GetBoolValue()), nil + return p.adapter.NativeToValue(c.GetBoolValue()), nil case *exprpb.Constant_BytesValue: - return types.Bytes(c.GetBytesValue()), nil + return p.adapter.NativeToValue(c.GetBytesValue()), nil case *exprpb.Constant_DoubleValue: - return types.Double(c.GetDoubleValue()), nil + return p.adapter.NativeToValue(c.GetDoubleValue()), nil case *exprpb.Constant_DurationValue: - return types.Duration{Duration: c.GetDurationValue().AsDuration()}, nil + return p.adapter.NativeToValue(c.GetDurationValue().AsDuration()), nil case *exprpb.Constant_Int64Value: - return types.Int(c.GetInt64Value()), nil + return p.adapter.NativeToValue(c.GetInt64Value()), nil case *exprpb.Constant_NullValue: - return types.Null(c.GetNullValue()), nil + return p.adapter.NativeToValue(c.GetNullValue()), nil case *exprpb.Constant_StringValue: - return types.String(c.GetStringValue()), nil + return p.adapter.NativeToValue(c.GetStringValue()), nil case *exprpb.Constant_TimestampValue: - return types.Timestamp{Time: c.GetTimestampValue().AsTime()}, nil + return p.adapter.NativeToValue(c.GetTimestampValue().AsTime()), nil case *exprpb.Constant_Uint64Value: - return types.Uint(c.GetUint64Value()), nil + return p.adapter.NativeToValue(c.GetUint64Value()), nil } return nil, fmt.Errorf("unknown constant type: %v", c) } diff --git a/vendor/github.com/google/cel-go/interpreter/prune.go b/vendor/github.com/google/cel-go/interpreter/prune.go index 7bcbb6c9e..0c01eb4f3 100644 --- a/vendor/github.com/google/cel-go/interpreter/prune.go +++ b/vendor/github.com/google/cel-go/interpreter/prune.go @@ -20,9 +20,8 @@ import ( "github.com/google/cel-go/common/types/ref" "github.com/google/cel-go/common/types/traits" - structpb "google.golang.org/protobuf/types/known/structpb" - exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" + structpb "google.golang.org/protobuf/types/known/structpb" ) type astPruner struct { @@ -229,7 +228,7 @@ func (p *astPruner) prune(node *exprpb.Expr) (*exprpb.Expr, bool) { } } - // We have either an unknown/error value, or something we dont want to + // We have either an unknown/error value, or something we don't want to // transform, or expression was not evaluated. If possible, drill down // more. diff --git a/vendor/github.com/google/cel-go/interpreter/runtimecost.go b/vendor/github.com/google/cel-go/interpreter/runtimecost.go new file mode 100644 index 000000000..06b6b27ef --- /dev/null +++ b/vendor/github.com/google/cel-go/interpreter/runtimecost.go @@ -0,0 +1,241 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package interpreter + +import ( + "math" + + "github.com/google/cel-go/common" + "github.com/google/cel-go/common/overloads" + "github.com/google/cel-go/common/types" + "github.com/google/cel-go/common/types/ref" + "github.com/google/cel-go/common/types/traits" +) + +// WARNING: Any changes to cost calculations in this file require a corresponding change in checker/cost.go + +// ActualCostEstimator provides function call cost estimations at runtime +// CallCost returns an estimated cost for the function overload invocation with the given args, or nil if it has no +// estimate to provide. CEL attempts to provide reasonable estimates for its standard function library, so CallCost +// should typically not need to provide an estimate for CELs standard function. +type ActualCostEstimator interface { + CallCost(function, overloadID string, args []ref.Val, result ref.Val) *uint64 +} + +// CostObserver provides an observer that tracks runtime cost. +func CostObserver(tracker *CostTracker) EvalObserver { + observer := func(id int64, programStep interface{}, val ref.Val) { + switch t := programStep.(type) { + case ConstantQualifier: + // TODO: Push identifiers on to the stack before observing constant qualifiers that apply to them + // and enable the below pop. Once enabled this can case can be collapsed into the Qualifier case. + tracker.cost++ + case InterpretableConst: + // zero cost + case InterpretableAttribute: + switch a := t.Attr().(type) { + case *conditionalAttribute: + // Ternary has no direct cost. All cost is from the conditional and the true/false branch expressions. + tracker.stack.drop(a.falsy.ID(), a.truthy.ID(), a.expr.ID()) + default: + tracker.stack.drop(t.Attr().ID()) + tracker.cost += common.SelectAndIdentCost + } + case *evalExhaustiveConditional: + // Ternary has no direct cost. All cost is from the conditional and the true/false branch expressions. + tracker.stack.drop(t.attr.falsy.ID(), t.attr.truthy.ID(), t.attr.expr.ID()) + + // While the field names are identical, the boolean operation eval structs do not share an interface and so + // must be handled individually. + case *evalOr: + tracker.stack.drop(t.rhs.ID(), t.lhs.ID()) + case *evalAnd: + tracker.stack.drop(t.rhs.ID(), t.lhs.ID()) + case *evalExhaustiveOr: + tracker.stack.drop(t.rhs.ID(), t.lhs.ID()) + case *evalExhaustiveAnd: + tracker.stack.drop(t.rhs.ID(), t.lhs.ID()) + case *evalFold: + tracker.stack.drop(t.iterRange.ID()) + case Qualifier: + tracker.cost++ + case InterpretableCall: + if argVals, ok := tracker.stack.dropArgs(t.Args()); ok { + tracker.cost += tracker.costCall(t, argVals, val) + } + case InterpretableConstructor: + tracker.stack.dropArgs(t.InitVals()) + switch t.Type() { + case types.ListType: + tracker.cost += common.ListCreateBaseCost + case types.MapType: + tracker.cost += common.MapCreateBaseCost + default: + tracker.cost += common.StructCreateBaseCost + } + } + tracker.stack.push(val, id) + + if tracker.Limit != nil && tracker.cost > *tracker.Limit { + panic(EvalCancelledError{Cause: CostLimitExceeded, Message: "operation cancelled: actual cost limit exceeded"}) + } + } + return observer +} + +// CostTracker represents the information needed for tacking runtime cost +type CostTracker struct { + Estimator ActualCostEstimator + Limit *uint64 + + cost uint64 + stack refValStack +} + +// ActualCost returns the runtime cost +func (c CostTracker) ActualCost() uint64 { + return c.cost +} + +func (c CostTracker) costCall(call InterpretableCall, argValues []ref.Val, result ref.Val) uint64 { + var cost uint64 + if c.Estimator != nil { + callCost := c.Estimator.CallCost(call.Function(), call.OverloadID(), argValues, result) + if callCost != nil { + cost += *callCost + return cost + } + } + // if user didn't specify, the default way of calculating runtime cost would be used. + // if user has their own implementation of ActualCostEstimator, make sure to cover the mapping between overloadId and cost calculation + switch call.OverloadID() { + // O(n) functions + case overloads.StartsWithString, overloads.EndsWithString, overloads.StringToBytes, overloads.BytesToString: + cost += uint64(math.Ceil(float64(c.actualSize(argValues[0])) * common.StringTraversalCostFactor)) + case overloads.InList: + // If a list is composed entirely of constant values this is O(1), but we don't account for that here. + // We just assume all list containment checks are O(n). + cost += c.actualSize(argValues[1]) + // O(min(m, n)) functions + case overloads.LessString, overloads.GreaterString, overloads.LessEqualsString, overloads.GreaterEqualsString, + overloads.LessBytes, overloads.GreaterBytes, overloads.LessEqualsBytes, overloads.GreaterEqualsBytes, + overloads.Equals, overloads.NotEquals: + // When we check the equality of 2 scalar values (e.g. 2 integers, 2 floating-point numbers, 2 booleans etc.), + // the CostTracker.actualSize() function by definition returns 1 for each operand, resulting in an overall cost + // of 1. + lhsSize := c.actualSize(argValues[0]) + rhsSize := c.actualSize(argValues[1]) + minSize := lhsSize + if rhsSize < minSize { + minSize = rhsSize + } + cost += uint64(math.Ceil(float64(minSize) * common.StringTraversalCostFactor)) + // O(m+n) functions + case overloads.AddString, overloads.AddBytes: + // In the worst case scenario, we would need to reallocate a new backing store and copy both operands over. + cost += uint64(math.Ceil(float64(c.actualSize(argValues[0])+c.actualSize(argValues[1])) * common.StringTraversalCostFactor)) + // O(nm) functions + case overloads.MatchesString: + // https://swtch.com/~rsc/regexp/regexp1.html applies to RE2 implementation supported by CEL + // Add one to string length for purposes of cost calculation to prevent product of string and regex to be 0 + // in case where string is empty but regex is still expensive. + strCost := uint64(math.Ceil((1.0 + float64(c.actualSize(argValues[0]))) * common.StringTraversalCostFactor)) + // We don't know how many expressions are in the regex, just the string length (a huge + // improvement here would be to somehow get a count the number of expressions in the regex or + // how many states are in the regex state machine and use that to measure regex cost). + // For now, we're making a guess that each expression in a regex is typically at least 4 chars + // in length. + regexCost := uint64(math.Ceil(float64(c.actualSize(argValues[1])) * common.RegexStringLengthCostFactor)) + cost += strCost * regexCost + case overloads.ContainsString: + strCost := uint64(math.Ceil(float64(c.actualSize(argValues[0])) * common.StringTraversalCostFactor)) + substrCost := uint64(math.Ceil(float64(c.actualSize(argValues[1])) * common.StringTraversalCostFactor)) + cost += strCost * substrCost + + default: + // The following operations are assumed to have O(1) complexity. + // - AddList due to the implementation. Index lookup can be O(c) the + // number of concatenated lists, but we don't track that is cost calculations. + // - Conversions, since none perform a traversal of a type of unbound length. + // - Computing the size of strings, byte sequences, lists and maps. + // - Logical operations and all operators on fixed width scalars (comparisons, equality) + // - Any functions that don't have a declared cost either here or in provided ActualCostEstimator. + cost++ + + } + return cost +} + +// actualSize returns the size of value +func (c CostTracker) actualSize(value ref.Val) uint64 { + if sz, ok := value.(traits.Sizer); ok { + return uint64(sz.Size().(types.Int)) + } + return 1 +} + +type stackVal struct { + Val ref.Val + ID int64 +} + +// refValStack keeps track of values of the stack for cost calculation purposes +type refValStack []stackVal + +func (s *refValStack) push(val ref.Val, id int64) { + value := stackVal{Val: val, ID: id} + *s = append(*s, value) +} + +// TODO: Allowing drop and dropArgs to remove stack items above the IDs they are provided is a workaround. drop and dropArgs +// should find and remove only the stack items matching the provided IDs once all attributes are properly pushed and popped from stack. + +// drop searches the stack for each ID and removes the ID and all stack items above it. +// If none of the IDs are found, the stack is not modified. +// WARNING: It is possible for multiple expressions with the same ID to exist (due to how macros are implemented) so it's +// possible that a dropped ID will remain on the stack. They should be removed when IDs on the stack are popped. +func (s *refValStack) drop(ids ...int64) { + for _, id := range ids { + for idx := len(*s) - 1; idx >= 0; idx-- { + if (*s)[idx].ID == id { + *s = (*s)[:idx] + break + } + } + } +} + +// dropArgs searches the stack for all the args by their IDs, accumulates their associated ref.Vals and drops any +// stack items above any of the arg IDs. If any of the IDs are not found the stack, false is returned. +// Args are assumed to be found in the stack in reverse order, i.e. the last arg is expected to be found highest in +// the stack. +// WARNING: It is possible for multiple expressions with the same ID to exist (due to how macros are implemented) so it's +// possible that a dropped ID will remain on the stack. They should be removed when IDs on the stack are popped. +func (s *refValStack) dropArgs(args []Interpretable) ([]ref.Val, bool) { + result := make([]ref.Val, len(args)) +argloop: + for nIdx := len(args) - 1; nIdx >= 0; nIdx-- { + for idx := len(*s) - 1; idx >= 0; idx-- { + if (*s)[idx].ID == args[nIdx].ID() { + el := (*s)[idx] + *s = (*s)[:idx] + result[nIdx] = el.Val + continue argloop + } + } + return nil, false + } + return result, true +} diff --git a/vendor/github.com/google/cel-go/parser/errors.go b/vendor/github.com/google/cel-go/parser/errors.go index 140beb953..ce49bb87f 100644 --- a/vendor/github.com/google/cel-go/parser/errors.go +++ b/vendor/github.com/google/cel-go/parser/errors.go @@ -28,15 +28,3 @@ type parseErrors struct { func (e *parseErrors) syntaxError(l common.Location, message string) { e.ReportError(l, fmt.Sprintf("Syntax error: %s", message)) } - -func (e *parseErrors) invalidHasArgument(l common.Location) { - e.ReportError(l, "Argument to the function 'has' must be a field selection") -} - -func (e *parseErrors) argumentIsNotIdent(l common.Location) { - e.ReportError(l, "Argument must be a simple name") -} - -func (e *parseErrors) notAQualifiedName(l common.Location) { - e.ReportError(l, "Expected a qualified name") -} diff --git a/vendor/github.com/google/cel-go/parser/gen/CEL.g4 b/vendor/github.com/google/cel-go/parser/gen/CEL.g4 index 792812028..11145ec37 100644 --- a/vendor/github.com/google/cel-go/parser/gen/CEL.g4 +++ b/vendor/github.com/google/cel-go/parser/gen/CEL.g4 @@ -83,9 +83,9 @@ literal | sign=MINUS? tok=NUM_FLOAT # Double | tok=STRING # String | tok=BYTES # Bytes - | tok='true' # BoolTrue - | tok='false' # BoolFalse - | tok='null' # Null + | tok=CEL_TRUE # BoolTrue + | tok=CEL_FALSE # BoolFalse + | tok=NUL # Null ; // Lexer Rules @@ -117,9 +117,9 @@ PLUS : '+'; STAR : '*'; SLASH : '/'; PERCENT : '%'; -TRUE : 'true'; -FALSE : 'false'; -NULL : 'null'; +CEL_TRUE : 'true'; +CEL_FALSE : 'false'; +NUL : 'null'; fragment BACKSLASH : '\\'; fragment LETTER : 'A'..'Z' | 'a'..'z' ; diff --git a/vendor/github.com/google/cel-go/parser/gen/CEL.tokens b/vendor/github.com/google/cel-go/parser/gen/CEL.tokens index c99e4c021..b305bdad3 100644 --- a/vendor/github.com/google/cel-go/parser/gen/CEL.tokens +++ b/vendor/github.com/google/cel-go/parser/gen/CEL.tokens @@ -23,9 +23,9 @@ PLUS=22 STAR=23 SLASH=24 PERCENT=25 -TRUE=26 -FALSE=27 -NULL=28 +CEL_TRUE=26 +CEL_FALSE=27 +NUL=28 WHITESPACE=29 COMMENT=30 NUM_FLOAT=31 diff --git a/vendor/github.com/google/cel-go/parser/gen/CELLexer.tokens b/vendor/github.com/google/cel-go/parser/gen/CELLexer.tokens index c99e4c021..b305bdad3 100644 --- a/vendor/github.com/google/cel-go/parser/gen/CELLexer.tokens +++ b/vendor/github.com/google/cel-go/parser/gen/CELLexer.tokens @@ -23,9 +23,9 @@ PLUS=22 STAR=23 SLASH=24 PERCENT=25 -TRUE=26 -FALSE=27 -NULL=28 +CEL_TRUE=26 +CEL_FALSE=27 +NUL=28 WHITESPACE=29 COMMENT=30 NUM_FLOAT=31 diff --git a/vendor/github.com/google/cel-go/parser/gen/cel_base_listener.go b/vendor/github.com/google/cel-go/parser/gen/cel_base_listener.go index 94f6c5881..a3315b842 100644 --- a/vendor/github.com/google/cel-go/parser/gen/cel_base_listener.go +++ b/vendor/github.com/google/cel-go/parser/gen/cel_base_listener.go @@ -1,4 +1,4 @@ -// Generated from /Users/tswadell/go/src/github.com/google/cel-go/bin/../parser/gen/CEL.g4 by ANTLR 4.7. +// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/bin/../parser/gen/CEL.g4 by ANTLR 4.9.1. DO NOT EDIT. package gen // CEL import "github.com/antlr/antlr4/runtime/Go/antlr" diff --git a/vendor/github.com/google/cel-go/parser/gen/cel_base_visitor.go b/vendor/github.com/google/cel-go/parser/gen/cel_base_visitor.go index bb46a64d5..daf7f807d 100644 --- a/vendor/github.com/google/cel-go/parser/gen/cel_base_visitor.go +++ b/vendor/github.com/google/cel-go/parser/gen/cel_base_visitor.go @@ -1,4 +1,4 @@ -// Generated from /Users/tswadell/go/src/github.com/google/cel-go/bin/../parser/gen/CEL.g4 by ANTLR 4.7. +// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/bin/../parser/gen/CEL.g4 by ANTLR 4.9.1. DO NOT EDIT. package gen // CEL import "github.com/antlr/antlr4/runtime/Go/antlr" diff --git a/vendor/github.com/google/cel-go/parser/gen/cel_lexer.go b/vendor/github.com/google/cel-go/parser/gen/cel_lexer.go index b76f78a65..4af96aba5 100644 --- a/vendor/github.com/google/cel-go/parser/gen/cel_lexer.go +++ b/vendor/github.com/google/cel-go/parser/gen/cel_lexer.go @@ -1,4 +1,4 @@ -// Generated from /Users/tswadell/go/src/github.com/google/cel-go/bin/../parser/gen/CEL.g4 by ANTLR 4.7. +// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/bin/../parser/gen/CEL.g4 by ANTLR 4.9.1. DO NOT EDIT. package gen @@ -233,18 +233,19 @@ var lexerSymbolicNames = []string{ "", "EQUALS", "NOT_EQUALS", "IN", "LESS", "LESS_EQUALS", "GREATER_EQUALS", "GREATER", "LOGICAL_AND", "LOGICAL_OR", "LBRACKET", "RPRACKET", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "DOT", "COMMA", "MINUS", "EXCLAM", "QUESTIONMARK", - "COLON", "PLUS", "STAR", "SLASH", "PERCENT", "TRUE", "FALSE", "NULL", "WHITESPACE", - "COMMENT", "NUM_FLOAT", "NUM_INT", "NUM_UINT", "STRING", "BYTES", "IDENTIFIER", + "COLON", "PLUS", "STAR", "SLASH", "PERCENT", "CEL_TRUE", "CEL_FALSE", "NUL", + "WHITESPACE", "COMMENT", "NUM_FLOAT", "NUM_INT", "NUM_UINT", "STRING", + "BYTES", "IDENTIFIER", } var lexerRuleNames = []string{ "EQUALS", "NOT_EQUALS", "IN", "LESS", "LESS_EQUALS", "GREATER_EQUALS", "GREATER", "LOGICAL_AND", "LOGICAL_OR", "LBRACKET", "RPRACKET", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "DOT", "COMMA", "MINUS", "EXCLAM", "QUESTIONMARK", - "COLON", "PLUS", "STAR", "SLASH", "PERCENT", "TRUE", "FALSE", "NULL", "BACKSLASH", - "LETTER", "DIGIT", "EXPONENT", "HEXDIGIT", "RAW", "ESC_SEQ", "ESC_CHAR_SEQ", - "ESC_OCT_SEQ", "ESC_BYTE_SEQ", "ESC_UNI_SEQ", "WHITESPACE", "COMMENT", - "NUM_FLOAT", "NUM_INT", "NUM_UINT", "STRING", "BYTES", "IDENTIFIER", + "COLON", "PLUS", "STAR", "SLASH", "PERCENT", "CEL_TRUE", "CEL_FALSE", "NUL", + "BACKSLASH", "LETTER", "DIGIT", "EXPONENT", "HEXDIGIT", "RAW", "ESC_SEQ", + "ESC_CHAR_SEQ", "ESC_OCT_SEQ", "ESC_BYTE_SEQ", "ESC_UNI_SEQ", "WHITESPACE", + "COMMENT", "NUM_FLOAT", "NUM_INT", "NUM_UINT", "STRING", "BYTES", "IDENTIFIER", } type CELLexer struct { @@ -254,8 +255,13 @@ type CELLexer struct { // TODO: EOF string } +// NewCELLexer produces a new lexer instance for the optional input antlr.CharStream. +// +// The *CELLexer instance produced may be reused by calling the SetInputStream method. +// The initial lexer configuration is expensive to construct, and the object is not thread-safe; +// however, if used within a Golang sync.Pool, the construction cost amortizes well and the +// objects can be used in a thread-safe manner. func NewCELLexer(input antlr.CharStream) *CELLexer { - l := new(CELLexer) lexerDeserializer := antlr.NewATNDeserializer(nil) lexerAtn := lexerDeserializer.DeserializeFromUInt16(serializedLexerAtn) @@ -263,7 +269,6 @@ func NewCELLexer(input antlr.CharStream) *CELLexer { for index, ds := range lexerAtn.DecisionToState { lexerDecisionToDFA[index] = antlr.NewDFA(ds, index) } - l.BaseLexer = antlr.NewBaseLexer(input) l.Interpreter = antlr.NewLexerATNSimulator(l, lexerAtn, lexerDecisionToDFA, antlr.NewPredictionContextCache()) @@ -305,9 +310,9 @@ const ( CELLexerSTAR = 23 CELLexerSLASH = 24 CELLexerPERCENT = 25 - CELLexerTRUE = 26 - CELLexerFALSE = 27 - CELLexerNULL = 28 + CELLexerCEL_TRUE = 26 + CELLexerCEL_FALSE = 27 + CELLexerNUL = 28 CELLexerWHITESPACE = 29 CELLexerCOMMENT = 30 CELLexerNUM_FLOAT = 31 diff --git a/vendor/github.com/google/cel-go/parser/gen/cel_listener.go b/vendor/github.com/google/cel-go/parser/gen/cel_listener.go index 9abfc1121..e555ae627 100644 --- a/vendor/github.com/google/cel-go/parser/gen/cel_listener.go +++ b/vendor/github.com/google/cel-go/parser/gen/cel_listener.go @@ -1,4 +1,4 @@ -// Generated from /Users/tswadell/go/src/github.com/google/cel-go/bin/../parser/gen/CEL.g4 by ANTLR 4.7. +// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/bin/../parser/gen/CEL.g4 by ANTLR 4.9.1. DO NOT EDIT. package gen // CEL import "github.com/antlr/antlr4/runtime/Go/antlr" diff --git a/vendor/github.com/google/cel-go/parser/gen/cel_parser.go b/vendor/github.com/google/cel-go/parser/gen/cel_parser.go index d99ed1c6a..c5e18930e 100644 --- a/vendor/github.com/google/cel-go/parser/gen/cel_parser.go +++ b/vendor/github.com/google/cel-go/parser/gen/cel_parser.go @@ -1,4 +1,4 @@ -// Generated from /Users/tswadell/go/src/github.com/google/cel-go/bin/../parser/gen/CEL.g4 by ANTLR 4.7. +// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/bin/../parser/gen/CEL.g4 by ANTLR 4.9.1. DO NOT EDIT. package gen // CEL import ( @@ -112,7 +112,6 @@ var parserATN = []uint16{ 2, 2, 31, 37, 44, 52, 63, 75, 77, 84, 90, 93, 103, 106, 116, 119, 122, 124, 128, 133, 136, 144, 147, 152, 155, 159, 166, 178, 191, 195, 200, 208, } - var literalNames = []string{ "", "'=='", "'!='", "'in'", "'<'", "'<='", "'>='", "'>'", "'&&'", "'||'", "'['", "']'", "'{'", "'}'", "'('", "')'", "'.'", "','", "'-'", "'!'", "'?'", @@ -122,8 +121,9 @@ var symbolicNames = []string{ "", "EQUALS", "NOT_EQUALS", "IN", "LESS", "LESS_EQUALS", "GREATER_EQUALS", "GREATER", "LOGICAL_AND", "LOGICAL_OR", "LBRACKET", "RPRACKET", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "DOT", "COMMA", "MINUS", "EXCLAM", "QUESTIONMARK", - "COLON", "PLUS", "STAR", "SLASH", "PERCENT", "TRUE", "FALSE", "NULL", "WHITESPACE", - "COMMENT", "NUM_FLOAT", "NUM_INT", "NUM_UINT", "STRING", "BYTES", "IDENTIFIER", + "COLON", "PLUS", "STAR", "SLASH", "PERCENT", "CEL_TRUE", "CEL_FALSE", "NUL", + "WHITESPACE", "COMMENT", "NUM_FLOAT", "NUM_INT", "NUM_UINT", "STRING", + "BYTES", "IDENTIFIER", } var ruleNames = []string{ @@ -136,6 +136,12 @@ type CELParser struct { *antlr.BaseParser } +// NewCELParser produces a new parser instance for the optional input antlr.TokenStream. +// +// The *CELParser instance produced may be reused by calling the SetInputStream method. +// The initial parser configuration is expensive to construct, and the object is not thread-safe; +// however, if used within a Golang sync.Pool, the construction cost amortizes well and the +// objects can be used in a thread-safe manner. func NewCELParser(input antlr.TokenStream) *CELParser { this := new(CELParser) deserializer := antlr.NewATNDeserializer(nil) @@ -144,7 +150,6 @@ func NewCELParser(input antlr.TokenStream) *CELParser { for index, ds := range deserializedATN.DecisionToState { decisionToDFA[index] = antlr.NewDFA(ds, index) } - this.BaseParser = antlr.NewBaseParser(input) this.Interpreter = antlr.NewParserATNSimulator(this, deserializedATN, decisionToDFA, antlr.NewPredictionContextCache()) @@ -184,9 +189,9 @@ const ( CELParserSTAR = 23 CELParserSLASH = 24 CELParserPERCENT = 25 - CELParserTRUE = 26 - CELParserFALSE = 27 - CELParserNULL = 28 + CELParserCEL_TRUE = 26 + CELParserCEL_FALSE = 27 + CELParserNUL = 28 CELParserWHITESPACE = 29 CELParserCOMMENT = 30 CELParserNUM_FLOAT = 31 @@ -448,6 +453,14 @@ func (s *ExprContext) ConditionalOr(i int) IConditionalOrContext { return t.(IConditionalOrContext) } +func (s *ExprContext) COLON() antlr.TerminalNode { + return s.GetToken(CELParserCOLON, 0) +} + +func (s *ExprContext) QUESTIONMARK() antlr.TerminalNode { + return s.GetToken(CELParserQUESTIONMARK, 0) +} + func (s *ExprContext) Expr() IExprContext { var t = s.GetTypedRuleContext(reflect.TypeOf((*IExprContext)(nil)).Elem(), 0) @@ -669,6 +682,14 @@ func (s *ConditionalOrContext) ConditionalAnd(i int) IConditionalAndContext { return t.(IConditionalAndContext) } +func (s *ConditionalOrContext) AllLOGICAL_OR() []antlr.TerminalNode { + return s.GetTokens(CELParserLOGICAL_OR) +} + +func (s *ConditionalOrContext) LOGICAL_OR(i int) antlr.TerminalNode { + return s.GetToken(CELParserLOGICAL_OR, i) +} + func (s *ConditionalOrContext) GetRuleContext() antlr.RuleContext { return s } @@ -874,6 +895,14 @@ func (s *ConditionalAndContext) Relation(i int) IRelationContext { return t.(IRelationContext) } +func (s *ConditionalAndContext) AllLOGICAL_AND() []antlr.TerminalNode { + return s.GetTokens(CELParserLOGICAL_AND) +} + +func (s *ConditionalAndContext) LOGICAL_AND(i int) antlr.TerminalNode { + return s.GetToken(CELParserLOGICAL_AND, i) +} + func (s *ConditionalAndContext) GetRuleContext() antlr.RuleContext { return s } @@ -1045,6 +1074,34 @@ func (s *RelationContext) Relation(i int) IRelationContext { return t.(IRelationContext) } +func (s *RelationContext) LESS() antlr.TerminalNode { + return s.GetToken(CELParserLESS, 0) +} + +func (s *RelationContext) LESS_EQUALS() antlr.TerminalNode { + return s.GetToken(CELParserLESS_EQUALS, 0) +} + +func (s *RelationContext) GREATER_EQUALS() antlr.TerminalNode { + return s.GetToken(CELParserGREATER_EQUALS, 0) +} + +func (s *RelationContext) GREATER() antlr.TerminalNode { + return s.GetToken(CELParserGREATER, 0) +} + +func (s *RelationContext) EQUALS() antlr.TerminalNode { + return s.GetToken(CELParserEQUALS, 0) +} + +func (s *RelationContext) NOT_EQUALS() antlr.TerminalNode { + return s.GetToken(CELParserNOT_EQUALS, 0) +} + +func (s *RelationContext) IN() antlr.TerminalNode { + return s.GetToken(CELParserIN, 0) +} + func (s *RelationContext) GetRuleContext() antlr.RuleContext { return s } @@ -1131,21 +1188,23 @@ func (p *CELParser) relation(_p int) (localctx IRelationContext) { if !(p.Precpred(p.GetParserRuleContext(), 1)) { panic(antlr.NewFailedPredicateException(p, "p.Precpred(p.GetParserRuleContext(), 1)", "")) } - p.SetState(57) + { + p.SetState(57) - var _lt = p.GetTokenStream().LT(1) + var _lt = p.GetTokenStream().LT(1) - localctx.(*RelationContext).op = _lt + localctx.(*RelationContext).op = _lt - _la = p.GetTokenStream().LA(1) + _la = p.GetTokenStream().LA(1) - if !(((_la)&-(0x1f+1)) == 0 && ((1<= c.buf.Len() { + panic("cannot consume EOF") + } + c.pos++ +} + +// LA implements (antlr.CharStream).LA. +func (c *charStream) LA(offset int) int { + if offset == 0 { + return 0 + } + if offset < 0 { + offset++ + } + pos := c.pos + offset - 1 + if pos < 0 || pos >= c.buf.Len() { + return antlr.TokenEOF + } + return int(c.buf.Get(pos)) +} + +// LT mimics (*antlr.InputStream).LT. +func (c *charStream) LT(offset int) int { + return c.LA(offset) +} + +// Mark implements (antlr.CharStream).Mark. +func (c *charStream) Mark() int { + return -1 +} + +// Release implements (antlr.CharStream).Release. +func (c *charStream) Release(marker int) {} + +// Index implements (antlr.CharStream).Index. +func (c *charStream) Index() int { + return c.pos +} + +// Seek implements (antlr.CharStream).Seek. +func (c *charStream) Seek(index int) { + if index <= c.pos { + c.pos = index + return + } + if index < c.buf.Len() { + c.pos = index + } else { + c.pos = c.buf.Len() + } +} + +// Size implements (antlr.CharStream).Size. +func (c *charStream) Size() int { + return c.buf.Len() +} + +// GetSourceName implements (antlr.CharStream).GetSourceName. +func (c *charStream) GetSourceName() string { + return c.src +} + +// GetText implements (antlr.CharStream).GetText. +func (c *charStream) GetText(start, stop int) string { + if stop >= c.buf.Len() { + stop = c.buf.Len() - 1 + } + if start >= c.buf.Len() { + return "" + } + return c.buf.Slice(start, stop+1) +} + +// GetTextFromTokens implements (antlr.CharStream).GetTextFromTokens. +func (c *charStream) GetTextFromTokens(start, stop antlr.Token) string { + if start != nil && stop != nil { + return c.GetText(start.GetTokenIndex(), stop.GetTokenIndex()) + } + return "" +} + +// GetTextFromInterval implements (antlr.CharStream).GetTextFromInterval. +func (c *charStream) GetTextFromInterval(i *antlr.Interval) string { + return c.GetText(i.Start, i.Stop) +} + +// String mimics (*antlr.InputStream).String. +func (c *charStream) String() string { + return c.buf.Slice(0, c.buf.Len()) +} + +var _ antlr.CharStream = &charStream{} + +func newCharStream(buf runes.Buffer, desc string) antlr.CharStream { + return &charStream{ + buf: buf, + src: desc, + } +} diff --git a/vendor/github.com/google/cel-go/parser/macro.go b/vendor/github.com/google/cel-go/parser/macro.go index de3fc4384..baeddd94e 100644 --- a/vendor/github.com/google/cel-go/parser/macro.go +++ b/vendor/github.com/google/cel-go/parser/macro.go @@ -285,7 +285,7 @@ func makeExistsOne(eh ExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*ex func makeQuantifier(kind quantifierKind, eh ExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error) { v, found := extractIdent(args[0]) if !found { - location := eh.OffsetLocation(args[0].Id) + location := eh.OffsetLocation(args[0].GetId()) return nil, &common.Error{ Message: "argument must be a simple name", Location: location} @@ -373,14 +373,14 @@ func makeFilter(eh ExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprp func extractIdent(e *exprpb.Expr) (string, bool) { switch e.ExprKind.(type) { case *exprpb.Expr_IdentExpr: - return e.GetIdentExpr().Name, true + return e.GetIdentExpr().GetName(), true } return "", false } func makeHas(eh ExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error) { if s, ok := args[0].ExprKind.(*exprpb.Expr_SelectExpr); ok { - return eh.PresenceTest(s.SelectExpr.Operand, s.SelectExpr.Field), nil + return eh.PresenceTest(s.SelectExpr.GetOperand(), s.SelectExpr.GetField()), nil } return nil, &common.Error{Message: "invalid argument to has() macro"} } diff --git a/vendor/github.com/google/cel-go/parser/options.go b/vendor/github.com/google/cel-go/parser/options.go new file mode 100644 index 000000000..b50686a91 --- /dev/null +++ b/vendor/github.com/google/cel-go/parser/options.go @@ -0,0 +1,104 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package parser + +import "fmt" + +type options struct { + maxRecursionDepth int + errorRecoveryTokenLookaheadLimit int + errorRecoveryLimit int + expressionSizeCodePointLimit int + macros map[string]Macro + populateMacroCalls bool +} + +// Option configures the behavior of the parser. +type Option func(*options) error + +// MaxRecursionDepth limits the maximum depth the parser will attempt to parse the expression before giving up. +func MaxRecursionDepth(limit int) Option { + return func(opts *options) error { + if limit < -1 { + return fmt.Errorf("max recursion depth must be greater than or equal to -1: %d", limit) + } + opts.maxRecursionDepth = limit + return nil + } +} + +// ErrorRecoveryLookaheadTokenLimit limits the number of lexer tokens that may be considered during error recovery. +// +// Error recovery often involves looking ahead in the input to determine if there's a point at which parsing may +// successfully resume. In some pathological cases, the parser can look through quite a large set of input which +// in turn generates a lot of back-tracking and performance degredation. +// +// The limit must be > 1, and is recommended to be less than the default of 256. +func ErrorRecoveryLookaheadTokenLimit(limit int) Option { + return func(opts *options) error { + if limit < 1 { + return fmt.Errorf("error recovery lookahead token limit must be at least 1: %d", limit) + } + opts.errorRecoveryTokenLookaheadLimit = limit + return nil + } +} + +// ErrorRecoveryLimit limits the number of attempts the parser will perform to recover from an error. +func ErrorRecoveryLimit(limit int) Option { + return func(opts *options) error { + if limit < -1 { + return fmt.Errorf("error recovery limit must be greater than or equal to -1: %d", limit) + } + opts.errorRecoveryLimit = limit + return nil + } +} + +// ExpressionSizeCodePointLimit is an option which limits the maximum code point count of an +// expression. +func ExpressionSizeCodePointLimit(expressionSizeCodePointLimit int) Option { + return func(opts *options) error { + if expressionSizeCodePointLimit < -1 { + return fmt.Errorf("expression size code point limit must be greater than or equal to -1: %d", expressionSizeCodePointLimit) + } + opts.expressionSizeCodePointLimit = expressionSizeCodePointLimit + return nil + } +} + +// Macros adds the given macros to the parser. +func Macros(macros ...Macro) Option { + return func(opts *options) error { + for _, m := range macros { + if m != nil { + if opts.macros == nil { + opts.macros = make(map[string]Macro) + } + opts.macros[m.MacroKey()] = m + } + } + return nil + } +} + +// PopulateMacroCalls ensures that the original call signatures replaced by expanded macros +// are preserved in the `SourceInfo` of parse result. +func PopulateMacroCalls(populateMacroCalls bool) Option { + return func(opts *options) error { + opts.populateMacroCalls = populateMacroCalls + return nil + } +} diff --git a/vendor/github.com/google/cel-go/parser/parser.go b/vendor/github.com/google/cel-go/parser/parser.go index ea473bd11..70dbdd7cf 100644 --- a/vendor/github.com/google/cel-go/parser/parser.go +++ b/vendor/github.com/google/cel-go/parser/parser.go @@ -23,52 +23,257 @@ import ( "sync" "github.com/antlr/antlr4/runtime/Go/antlr" - "github.com/google/cel-go/common" "github.com/google/cel-go/common/operators" + "github.com/google/cel-go/common/runes" "github.com/google/cel-go/parser/gen" - structpb "google.golang.org/protobuf/types/known/structpb" exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" + structpb "google.golang.org/protobuf/types/known/structpb" ) +// Parser encapsulates the context necessary to perform parsing for different expressions. +type Parser struct { + options +} + +// NewParser builds and returns a new Parser using the provided options. +func NewParser(opts ...Option) (*Parser, error) { + p := &Parser{} + for _, opt := range opts { + if err := opt(&p.options); err != nil { + return nil, err + } + } + if p.maxRecursionDepth == 0 { + p.maxRecursionDepth = 200 + } + if p.maxRecursionDepth == -1 { + p.maxRecursionDepth = int((^uint(0)) >> 1) + } + if p.errorRecoveryTokenLookaheadLimit == 0 { + p.errorRecoveryTokenLookaheadLimit = 256 + } + if p.errorRecoveryLimit == 0 { + p.errorRecoveryLimit = 30 + } + if p.errorRecoveryLimit == -1 { + p.errorRecoveryLimit = int((^uint(0)) >> 1) + } + if p.expressionSizeCodePointLimit == 0 { + p.expressionSizeCodePointLimit = 100_000 + } + if p.expressionSizeCodePointLimit == -1 { + p.expressionSizeCodePointLimit = int((^uint(0)) >> 1) + } + // Bool is false by default, so populateMacroCalls will be false by default + return p, nil +} + +// mustNewParser does the work of NewParser and panics if an error occurs. +// +// This function is only intended for internal use and is for backwards compatibility in Parse and +// ParseWithMacros, where we know the options will result in an error. +func mustNewParser(opts ...Option) *Parser { + p, err := NewParser(opts...) + if err != nil { + panic(err) + } + return p +} + +// Parse parses the expression represented by source and returns the result. +func (p *Parser) Parse(source common.Source) (*exprpb.ParsedExpr, *common.Errors) { + impl := parser{ + errors: &parseErrors{common.NewErrors(source)}, + helper: newParserHelper(source), + macros: p.macros, + maxRecursionDepth: p.maxRecursionDepth, + errorRecoveryLimit: p.errorRecoveryLimit, + errorRecoveryLookaheadTokenLimit: p.errorRecoveryTokenLookaheadLimit, + populateMacroCalls: p.populateMacroCalls, + } + buf, ok := source.(runes.Buffer) + if !ok { + buf = runes.NewBuffer(source.Content()) + } + var e *exprpb.Expr + if buf.Len() > p.expressionSizeCodePointLimit { + e = impl.reportError(common.NoLocation, + "expression code point size exceeds limit: size: %d, limit %d", + buf.Len(), p.expressionSizeCodePointLimit) + } else { + e = impl.parse(buf, source.Description()) + } + return &exprpb.ParsedExpr{ + Expr: e, + SourceInfo: impl.helper.getSourceInfo(), + }, impl.errors.Errors +} + // reservedIds are not legal to use as variables. We exclude them post-parse, as they *are* valid // field names for protos, and it would complicate the grammar to distinguish the cases. -var reservedIds = []string{ - "as", "break", "const", "continue", "else", "false", "for", "function", "if", - "import", "in", "let", "loop", "package", "namespace", "null", "return", - "true", "var", "void", "while", +var reservedIds = map[string]struct{}{ + "as": {}, + "break": {}, + "const": {}, + "continue": {}, + "else": {}, + "false": {}, + "for": {}, + "function": {}, + "if": {}, + "import": {}, + "in": {}, + "let": {}, + "loop": {}, + "package": {}, + "namespace": {}, + "null": {}, + "return": {}, + "true": {}, + "var": {}, + "void": {}, + "while": {}, } // Parse converts a source input a parsed expression. // This function calls ParseWithMacros with AllMacros. +// +// Deprecated: Use NewParser().Parse() instead. func Parse(source common.Source) (*exprpb.ParsedExpr, *common.Errors) { - return ParseWithMacros(source, AllMacros) + return mustNewParser(Macros(AllMacros...)).Parse(source) } -// ParseWithMacros converts a source input and macros set to a parsed expression. -func ParseWithMacros(source common.Source, macros []Macro) (*exprpb.ParsedExpr, *common.Errors) { - macroMap := make(map[string]Macro) - for _, m := range macros { - macroMap[m.MacroKey()] = m - } - p := parser{ - errors: &parseErrors{common.NewErrors(source)}, - helper: newParserHelper(source), - macros: macroMap, - } - e := p.parse(source.Content()) - return &exprpb.ParsedExpr{ - Expr: e, - SourceInfo: p.helper.getSourceInfo(), - }, p.errors.Errors +type recursionError struct { + message string } +// Error implements error. +func (re *recursionError) Error() string { + return re.message +} + +var _ error = &recursionError{} + +type recursionListener struct { + maxDepth int + ruleTypeDepth map[int]*int +} + +func (rl *recursionListener) VisitTerminal(node antlr.TerminalNode) {} + +func (rl *recursionListener) VisitErrorNode(node antlr.ErrorNode) {} + +func (rl *recursionListener) EnterEveryRule(ctx antlr.ParserRuleContext) { + if ctx == nil { + return + } + ruleIndex := ctx.GetRuleIndex() + depth, found := rl.ruleTypeDepth[ruleIndex] + if !found { + var counter = 1 + rl.ruleTypeDepth[ruleIndex] = &counter + depth = &counter + } else { + *depth++ + } + if *depth >= rl.maxDepth { + panic(&recursionError{ + message: fmt.Sprintf("expression recursion limit exceeded: %d", rl.maxDepth), + }) + } +} + +func (rl *recursionListener) ExitEveryRule(ctx antlr.ParserRuleContext) { + if ctx == nil { + return + } + ruleIndex := ctx.GetRuleIndex() + if depth, found := rl.ruleTypeDepth[ruleIndex]; found && *depth > 0 { + *depth-- + } +} + +var _ antlr.ParseTreeListener = &recursionListener{} + +type recoveryLimitError struct { + message string +} + +// Error implements error. +func (rl *recoveryLimitError) Error() string { + return rl.message +} + +type lookaheadLimitError struct { + message string +} + +func (ll *lookaheadLimitError) Error() string { + return ll.message +} + +var _ error = &recoveryLimitError{} + +type recoveryLimitErrorStrategy struct { + *antlr.DefaultErrorStrategy + errorRecoveryLimit int + errorRecoveryTokenLookaheadLimit int + recoveryAttempts int +} + +type lookaheadConsumer struct { + antlr.Parser + errorRecoveryTokenLookaheadLimit int + lookaheadAttempts int +} + +func (lc *lookaheadConsumer) Consume() antlr.Token { + if lc.lookaheadAttempts >= lc.errorRecoveryTokenLookaheadLimit { + panic(&lookaheadLimitError{ + message: fmt.Sprintf("error recovery token lookahead limit exceeded: %d", lc.errorRecoveryTokenLookaheadLimit), + }) + } + lc.lookaheadAttempts++ + return lc.Parser.Consume() +} + +func (rl *recoveryLimitErrorStrategy) Recover(recognizer antlr.Parser, e antlr.RecognitionException) { + rl.checkAttempts(recognizer) + lc := &lookaheadConsumer{Parser: recognizer, errorRecoveryTokenLookaheadLimit: rl.errorRecoveryTokenLookaheadLimit} + rl.DefaultErrorStrategy.Recover(lc, e) +} + +func (rl *recoveryLimitErrorStrategy) RecoverInline(recognizer antlr.Parser) antlr.Token { + rl.checkAttempts(recognizer) + lc := &lookaheadConsumer{Parser: recognizer, errorRecoveryTokenLookaheadLimit: rl.errorRecoveryTokenLookaheadLimit} + return rl.DefaultErrorStrategy.RecoverInline(lc) +} + +func (rl *recoveryLimitErrorStrategy) checkAttempts(recognizer antlr.Parser) { + if rl.recoveryAttempts == rl.errorRecoveryLimit { + rl.recoveryAttempts++ + msg := fmt.Sprintf("error recovery attempt limit exceeded: %d", rl.errorRecoveryLimit) + recognizer.NotifyErrorListeners(msg, nil, nil) + panic(&recoveryLimitError{ + message: msg, + }) + } + rl.recoveryAttempts++ +} + +var _ antlr.ErrorStrategy = &recoveryLimitErrorStrategy{} + type parser struct { gen.BaseCELVisitor - errors *parseErrors - helper *parserHelper - macros map[string]Macro + errors *parseErrors + helper *parserHelper + macros map[string]Macro + maxRecursionDepth int + errorRecoveryLimit int + errorRecoveryLookaheadTokenLimit int + populateMacroCalls bool } var ( @@ -76,30 +281,71 @@ var ( lexerPool *sync.Pool = &sync.Pool{ New: func() interface{} { - return gen.NewCELLexer(nil) + l := gen.NewCELLexer(nil) + l.RemoveErrorListeners() + return l }, } parserPool *sync.Pool = &sync.Pool{ New: func() interface{} { - return gen.NewCELParser(nil) + p := gen.NewCELParser(nil) + p.RemoveErrorListeners() + return p }, } ) -func (p *parser) parse(expression string) *exprpb.Expr { +func (p *parser) parse(expr runes.Buffer, desc string) *exprpb.Expr { + // TODO: get rid of these pools once https://github.com/antlr/antlr4/pull/3571 is in a release lexer := lexerPool.Get().(*gen.CELLexer) - lexer.SetInputStream(antlr.NewInputStream(expression)) - defer lexerPool.Put(lexer) - prsr := parserPool.Get().(*gen.CELParser) - prsr.SetInputStream(antlr.NewCommonTokenStream(lexer, 0)) - defer parserPool.Put(prsr) - lexer.RemoveErrorListeners() - prsr.RemoveErrorListeners() + // Unfortunately ANTLR Go runtime is missing (*antlr.BaseParser).RemoveParseListeners, so this is + // good enough until that is exported. + prsrListener := &recursionListener{ + maxDepth: p.maxRecursionDepth, + ruleTypeDepth: map[int]*int{}, + } + + defer func() { + // Reset the lexer and parser before putting them back in the pool. + lexer.RemoveErrorListeners() + prsr.RemoveParseListener(prsrListener) + prsr.RemoveErrorListeners() + lexer.SetInputStream(nil) + prsr.SetInputStream(nil) + lexerPool.Put(lexer) + parserPool.Put(prsr) + }() + + lexer.SetInputStream(newCharStream(expr, desc)) + prsr.SetInputStream(antlr.NewCommonTokenStream(lexer, 0)) + lexer.AddErrorListener(p) prsr.AddErrorListener(p) + prsr.AddParseListener(prsrListener) + + prsr.SetErrorHandler(&recoveryLimitErrorStrategy{ + DefaultErrorStrategy: antlr.NewDefaultErrorStrategy(), + errorRecoveryLimit: p.errorRecoveryLimit, + errorRecoveryTokenLookaheadLimit: p.errorRecoveryLookaheadTokenLimit, + }) + + defer func() { + if val := recover(); val != nil { + switch err := val.(type) { + case *lookaheadLimitError: + p.errors.ReportError(common.NoLocation, err.Error()) + case *recursionError: + p.errors.ReportError(common.NoLocation, err.Error()) + case *recoveryLimitError: + // do nothing, listeners already notified and error reported. + default: + panic(val) + } + } + }() return p.Visit(prsr.Start()).(*exprpb.Expr) } @@ -372,10 +618,8 @@ func (p *parser) VisitIdentOrGlobalCall(ctx *gen.IdentOrGlobalCallContext) inter } // Handle reserved identifiers. id := ctx.GetId().GetText() - for _, r := range reservedIds { - if r == id { - return p.reportError(ctx, "reserved identifier: %s", r) - } + if _, ok := reservedIds[id]; ok { + return p.reportError(ctx, "reserved identifier: %s", id) } identName += id if ctx.GetOp() != nil { @@ -557,7 +801,7 @@ func (p *parser) extractQualifiedName(e *exprpb.Expr) (string, bool) { } switch e.ExprKind.(type) { case *exprpb.Expr_IdentExpr: - return e.GetIdentExpr().Name, true + return e.GetIdentExpr().GetName(), true case *exprpb.Expr_SelectExpr: s := e.GetSelectExpr() if prefix, found := p.extractQualifiedName(s.Operand); found { @@ -565,7 +809,7 @@ func (p *parser) extractQualifiedName(e *exprpb.Expr) (string, bool) { } } // TODO: Add a method to Source to get location from character offset. - location := p.helper.getLocation(e.Id) + location := p.helper.getLocation(e.GetId()) p.reportError(location, "expected a qualified name") return "", false } @@ -586,7 +830,7 @@ func (p *parser) reportError(ctx interface{}, format string, args ...interface{} location = ctx.(common.Location) case antlr.Token, antlr.ParserRuleContext: err := p.helper.newExpr(ctx) - location = p.helper.getLocation(err.Id) + location = p.helper.getLocation(err.GetId()) } err := p.helper.newExpr(ctx) // Provide arguments to the report error. @@ -646,5 +890,8 @@ func (p *parser) expandMacro(exprID int64, function string, target *exprpb.Expr, } return p.reportError(p.helper.getLocation(exprID), err.Message), true } + if p.populateMacroCalls { + p.helper.addMacroCall(expr.GetId(), function, target, args...) + } return expr, true } diff --git a/vendor/github.com/google/cel-go/parser/unparser.go b/vendor/github.com/google/cel-go/parser/unparser.go index 654f4b957..6a610ff76 100644 --- a/vendor/github.com/google/cel-go/parser/unparser.go +++ b/vendor/github.com/google/cel-go/parser/unparser.go @@ -15,6 +15,7 @@ package parser import ( + "errors" "fmt" "strconv" "strings" @@ -46,19 +47,21 @@ func Unparse(expr *exprpb.Expr, info *exprpb.SourceInfo) (string, error) { // unparser visits an expression to reconstruct a human-readable string from an AST. type unparser struct { - str strings.Builder - offset int32 - // TODO: use the source info to rescontruct macros into function calls. + str strings.Builder info *exprpb.SourceInfo } func (un *unparser) visit(expr *exprpb.Expr) error { + if expr == nil { + return errors.New("unsupported expression") + } + visited, err := un.visitMaybeMacroCall(expr) + if visited || err != nil { + return err + } switch expr.ExprKind.(type) { case *exprpb.Expr_CallExpr: return un.visitCall(expr) - // TODO: Comprehensions are currently not supported. - case *exprpb.Expr_ComprehensionExpr: - return un.visitComprehension(expr) case *exprpb.Expr_ConstExpr: return un.visitConst(expr) case *exprpb.Expr_IdentExpr: @@ -69,8 +72,9 @@ func (un *unparser) visit(expr *exprpb.Expr) error { return un.visitSelect(expr) case *exprpb.Expr_StructExpr: return un.visitStruct(expr) + default: + return fmt.Errorf("unsupported expression: %v", expr) } - return fmt.Errorf("unsupported expr: %v", expr) } func (un *unparser) visitCall(expr *exprpb.Expr) error { @@ -220,12 +224,6 @@ func (un *unparser) visitCallUnary(expr *exprpb.Expr) error { return un.visitMaybeNested(args[0], nested) } -func (un *unparser) visitComprehension(expr *exprpb.Expr) error { - // TODO: introduce a macro expansion map between the top-level comprehension id and the - // function call that the macro replaces. - return fmt.Errorf("unimplemented : %v", expr) -} - func (un *unparser) visitConst(expr *exprpb.Expr) error { c := expr.GetConstExpr() switch c.ConstantKind.(type) { @@ -255,7 +253,7 @@ func (un *unparser) visitConst(expr *exprpb.Expr) error { un.str.WriteString(ui) un.str.WriteString("u") default: - return fmt.Errorf("unimplemented : %v", expr) + return fmt.Errorf("unsupported constant: %v", expr) } return nil } @@ -357,6 +355,15 @@ func (un *unparser) visitStructMap(expr *exprpb.Expr) error { return nil } +func (un *unparser) visitMaybeMacroCall(expr *exprpb.Expr) (bool, error) { + macroCalls := un.info.GetMacroCalls() + call, found := macroCalls[expr.GetId()] + if !found { + return false, nil + } + return true, un.visit(call) +} + func (un *unparser) visitMaybeNested(expr *exprpb.Expr, nested bool) error { if nested { un.str.WriteString("(") @@ -395,9 +402,6 @@ func isSamePrecedence(op string, expr *exprpb.Expr) bool { // // If the expr is not a Call, the result is false. func isLowerPrecedence(op string, expr *exprpb.Expr) bool { - if expr.GetCallExpr() == nil { - return false - } c := expr.GetCallExpr() other := c.GetFunction() return operators.Precedence(op) < operators.Precedence(other) diff --git a/vendor/github.com/google/go-containerregistry/pkg/authn/authn.go b/vendor/github.com/google/go-containerregistry/pkg/authn/authn.go index 690e81d05..172d218e4 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/authn/authn.go +++ b/vendor/github.com/google/go-containerregistry/pkg/authn/authn.go @@ -14,6 +14,19 @@ package authn +import ( + "encoding/base64" + "encoding/json" + "fmt" + "strings" +) + +// Authenticator is used to authenticate Docker transports. +type Authenticator interface { + // Authorization returns the value to use in an http transport's Authorization header. + Authorization() (*AuthConfig, error) +} + // AuthConfig contains authorization information for connecting to a Registry // Inlined what we use from github.com/docker/cli/cli/config/types type AuthConfig struct { @@ -29,8 +42,74 @@ type AuthConfig struct { RegistryToken string `json:"registrytoken,omitempty"` } -// Authenticator is used to authenticate Docker transports. -type Authenticator interface { - // Authorization returns the value to use in an http transport's Authorization header. - Authorization() (*AuthConfig, error) +// This is effectively a copy of the type AuthConfig. This simplifies +// JSON unmarshalling since AuthConfig methods are not inherited +type authConfig AuthConfig + +// UnmarshalJSON implements json.Unmarshaler +func (a *AuthConfig) UnmarshalJSON(data []byte) error { + var shadow authConfig + err := json.Unmarshal(data, &shadow) + if err != nil { + return err + } + + *a = (AuthConfig)(shadow) + + if len(shadow.Auth) != 0 { + var derr error + a.Username, a.Password, derr = decodeDockerConfigFieldAuth(shadow.Auth) + if derr != nil { + err = fmt.Errorf("unable to decode auth field: %w", derr) + } + } else if len(a.Username) != 0 && len(a.Password) != 0 { + a.Auth = encodeDockerConfigFieldAuth(shadow.Username, shadow.Password) + } + + return err +} + +// MarshalJSON implements json.Marshaler +func (a AuthConfig) MarshalJSON() ([]byte, error) { + shadow := (authConfig)(a) + shadow.Auth = encodeDockerConfigFieldAuth(shadow.Username, shadow.Password) + return json.Marshal(shadow) +} + +// decodeDockerConfigFieldAuth deserializes the "auth" field from dockercfg into a +// username and a password. The format of the auth field is base64(:). +// +// From https://github.com/kubernetes/kubernetes/blob/75e49ec824b183288e1dbaccfd7dbe77d89db381/pkg/credentialprovider/config.go +// Copyright 2014 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 +func decodeDockerConfigFieldAuth(field string) (username, password string, err error) { + var decoded []byte + // StdEncoding can only decode padded string + // RawStdEncoding can only decode unpadded string + if strings.HasSuffix(strings.TrimSpace(field), "=") { + // decode padded data + decoded, err = base64.StdEncoding.DecodeString(field) + } else { + // decode unpadded data + decoded, err = base64.RawStdEncoding.DecodeString(field) + } + + if err != nil { + return + } + + parts := strings.SplitN(string(decoded), ":", 2) + if len(parts) != 2 { + err = fmt.Errorf("must be formatted as base64(username:password)") + return + } + + username = parts[0] + password = parts[1] + + return +} + +func encodeDockerConfigFieldAuth(username, password string) string { + return base64.StdEncoding.EncodeToString([]byte(username + ":" + password)) } diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/options.go b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/options.go index 919013b1a..8bfd06d78 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/options.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/options.go @@ -102,7 +102,6 @@ var DefaultTransport = &http.Transport{ func makeOptions(target authn.Resource, opts ...Option) (*options, error) { o := &options{ - auth: authn.Anonymous, transport: DefaultTransport, platform: defaultPlatform, context: context.Background(), @@ -118,12 +117,19 @@ func makeOptions(target authn.Resource, opts ...Option) (*options, error) { } } - if o.keychain != nil { + switch { + case o.auth != nil && o.keychain != nil: + // It is a better experience to explicitly tell a caller their auth is misconfigured + // than potentially fail silently when the correct auth is overridden by option misuse. + return nil, errors.New("provide an option for either authn.Authenticator or authn.Keychain, not both") + case o.keychain != nil: auth, err := o.keychain.Resolve(target) if err != nil { return nil, err } o.auth = auth + case o.auth == nil: + o.auth = authn.Anonymous } // transport.Wrapper is a signal that consumers are opt-ing into providing their own transport without any additional wrapping. @@ -163,6 +169,7 @@ func WithTransport(t http.RoundTripper) Option { // WithAuth is a functional option for overriding the default authenticator // for remote operations. +// It is an error to use both WithAuth and WithAuthFromKeychain in the same Option set. // // The default authenticator is authn.Anonymous. func WithAuth(auth authn.Authenticator) Option { @@ -175,6 +182,7 @@ func WithAuth(auth authn.Authenticator) Option { // WithAuthFromKeychain is a functional option for overriding the default // authenticator for remote operations, using an authn.Keychain to find // credentials. +// It is an error to use both WithAuth and WithAuthFromKeychain in the same Option set. // // The default authenticator is authn.Anonymous. func WithAuthFromKeychain(keys authn.Keychain) Option { diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/bearer.go b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/bearer.go index 37bbab21b..ce4e70726 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/bearer.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/transport/bearer.go @@ -87,26 +87,24 @@ func (bt *bearerTransport) RoundTrip(in *http.Request) (*http.Response, error) { // If we hit a WWW-Authenticate challenge, it might be due to expired tokens or insufficient scope. if challenges := authchallenge.ResponseChallenges(res); len(challenges) != 0 { + newScopes := []string{} for _, wac := range challenges { // TODO(jonjohnsonjr): Should we also update "realm" or "service"? - if scope, ok := wac.Parameters["scope"]; ok { - // From https://tools.ietf.org/html/rfc6750#section-3 - // The "scope" attribute is defined in Section 3.3 of [RFC6749]. The - // "scope" attribute is a space-delimited list of case-sensitive scope - // values indicating the required scope of the access token for - // accessing the requested resource. - scopes := strings.Split(scope, " ") - + if want, ok := wac.Parameters["scope"]; ok { // Add any scopes that we don't already request. got := stringSet(bt.scopes) - for _, want := range scopes { - if _, ok := got[want]; !ok { - bt.scopes = append(bt.scopes, want) - } + if _, ok := got[want]; !ok { + newScopes = append(newScopes, want) } } } + // Some registries seem to only look at the first scope parameter during a token exchange. + // If a request fails because it's missing a scope, we should put those at the beginning, + // otherwise the registry might just ignore it :/ + newScopes = append(newScopes, bt.scopes...) + bt.scopes = newScopes + // TODO(jonjohnsonjr): Teach transport.Error about "error" and "error_description" from challenge. // Retry the request to attempt to get a valid token. diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/write.go b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/write.go index 41b19fcae..d412f953c 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/remote/write.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/remote/write.go @@ -410,33 +410,33 @@ func (w *writer) incrProgress(written int64) { // uploadOne performs a complete upload of a single layer. func (w *writer) uploadOne(ctx context.Context, l v1.Layer) error { - var from, mount string - if h, err := l.Digest(); err == nil { - // If we know the digest, this isn't a streaming layer. Do an existence - // check so we can skip uploading the layer if possible. - existing, err := w.checkExistingBlob(h) - if err != nil { - return err - } - if existing { - size, err := l.Size() + tryUpload := func() error { + var from, mount string + if h, err := l.Digest(); err == nil { + // If we know the digest, this isn't a streaming layer. Do an existence + // check so we can skip uploading the layer if possible. + existing, err := w.checkExistingBlob(h) if err != nil { return err } - w.incrProgress(size) - logs.Progress.Printf("existing blob: %v", h) - return nil + if existing { + size, err := l.Size() + if err != nil { + return err + } + w.incrProgress(size) + logs.Progress.Printf("existing blob: %v", h) + return nil + } + + mount = h.String() + } + if ml, ok := l.(*MountableLayer); ok { + if w.repo.RegistryStr() == ml.Reference.Context().RegistryStr() { + from = ml.Reference.Context().RepositoryStr() + } } - mount = h.String() - } - if ml, ok := l.(*MountableLayer); ok { - if w.repo.RegistryStr() == ml.Reference.Context().RegistryStr() { - from = ml.Reference.Context().RepositoryStr() - } - } - - tryUpload := func() error { location, mounted, err := w.initiateUpload(from, mount) if err != nil { return err diff --git a/vendor/k8s.io/cli-runtime/pkg/genericclioptions/command_headers.go b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/command_headers.go index 8f9e77475..0eea122fe 100644 --- a/vendor/k8s.io/cli-runtime/pkg/genericclioptions/command_headers.go +++ b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/command_headers.go @@ -25,8 +25,8 @@ import ( ) const ( - kubectlCommandHeader = "X-Kubectl-Command" - kubectlSessionHeader = "X-Kubectl-Session" + kubectlCommandHeader = "Kubectl-Command" + kubectlSessionHeader = "Kubectl-Session" ) // CommandHeaderRoundTripper adds a layer around the standard @@ -48,8 +48,8 @@ func (c *CommandHeaderRoundTripper) RoundTrip(req *http.Request) (*http.Response return c.Delegate.RoundTrip(req) } -// ParseCommandHeaders fills in a map of X-Headers into the CommandHeaderRoundTripper. These -// headers are then filled into each request. For details on X-Headers see: +// ParseCommandHeaders fills in a map of custom headers into the CommandHeaderRoundTripper. These +// headers are then filled into each request. For details on the custom headers see: // https://github.com/kubernetes/enhancements/tree/master/keps/sig-cli/859-kubectl-headers // Each call overwrites the previously parsed command headers (not additive). // TODO(seans3): Parse/add flags removing PII from flag values. @@ -77,3 +77,15 @@ func (c *CommandHeaderRoundTripper) ParseCommandHeaders(cmd *cobra.Command, args c.Headers[kubectlCommandHeader] = strings.Join(cmdStrs, " ") } } + +// CancelRequest is propagated to the Delegate RoundTripper within +// if the wrapped RoundTripper implements this function. +func (c *CommandHeaderRoundTripper) CancelRequest(req *http.Request) { + type canceler interface { + CancelRequest(*http.Request) + } + // If possible, call "CancelRequest" on the wrapped Delegate RoundTripper. + if cr, ok := c.Delegate.(canceler); ok { + cr.CancelRequest(req) + } +} diff --git a/vendor/k8s.io/cli-runtime/pkg/genericclioptions/record_flags.go b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/record_flags.go index 095a7b519..a5f307de5 100644 --- a/vendor/k8s.io/cli-runtime/pkg/genericclioptions/record_flags.go +++ b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/record_flags.go @@ -93,6 +93,7 @@ func (f *RecordFlags) AddFlags(cmd *cobra.Command) { if f.Record != nil { cmd.Flags().BoolVar(f.Record, "record", *f.Record, "Record current kubectl command in the resource annotation. If set to false, do not record the command. If set to true, record the command. If not set, default to updating the existing annotation value only if one already exists.") + cmd.Flags().MarkDeprecated("record", "--record will be removed in the future") } } diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/tableprinter.go b/vendor/k8s.io/cli-runtime/pkg/printers/tableprinter.go index 048cb66a2..c32e5fdf6 100644 --- a/vendor/k8s.io/cli-runtime/pkg/printers/tableprinter.go +++ b/vendor/k8s.io/cli-runtime/pkg/printers/tableprinter.go @@ -208,7 +208,23 @@ func printTable(table *metav1.Table, output io.Writer, options PrintOptions) err fmt.Fprint(output, "\t") } if cell != nil { - fmt.Fprint(output, cell) + switch val := cell.(type) { + case string: + print := val + truncated := false + // truncate at newlines + newline := strings.Index(print, "\n") + if newline >= 0 { + truncated = true + print = print[:newline] + } + fmt.Fprint(output, print) + if truncated { + fmt.Fprint(output, "...") + } + default: + fmt.Fprint(output, val) + } } } fmt.Fprintln(output) diff --git a/vendor/k8s.io/cli-runtime/pkg/resource/builder.go b/vendor/k8s.io/cli-runtime/pkg/resource/builder.go index a8ebf6410..87922680e 100644 --- a/vendor/k8s.io/cli-runtime/pkg/resource/builder.go +++ b/vendor/k8s.io/cli-runtime/pkg/resource/builder.go @@ -38,7 +38,7 @@ import ( "k8s.io/client-go/discovery" "k8s.io/client-go/rest" "k8s.io/client-go/restmapper" - "sigs.k8s.io/kustomize/api/filesys" + "sigs.k8s.io/kustomize/kyaml/filesys" ) var FileExtensions = []string{".json", ".yaml", ".yml"} @@ -72,9 +72,10 @@ type Builder struct { errs []error - paths []Visitor - stream bool - dir bool + paths []Visitor + stream bool + stdinInUse bool + dir bool labelSelector *string fieldSelector *string @@ -121,6 +122,8 @@ Example resource specifications include: '-f rsrc.yaml' '--filename=rsrc.json'`) +var StdinMultiUseError = errors.New("standard input cannot be used for multiple arguments") + // TODO: expand this to include other errors. func IsUsageError(err error) bool { if err == nil { @@ -362,13 +365,31 @@ func (b *Builder) URL(httpAttemptCount int, urls ...*url.URL) *Builder { // Stdin will read objects from the standard input. If ContinueOnError() is set // prior to this method being called, objects in the stream that are unrecognized -// will be ignored (but logged at V(2)). +// will be ignored (but logged at V(2)). If StdinInUse() is set prior to this method +// being called, an error will be recorded as there are multiple entities trying to use +// the single standard input stream. func (b *Builder) Stdin() *Builder { b.stream = true + if b.stdinInUse { + b.errs = append(b.errs, StdinMultiUseError) + } + b.stdinInUse = true b.paths = append(b.paths, FileVisitorForSTDIN(b.mapper, b.schema)) return b } +// StdinInUse will mark standard input as in use by this Builder, and therefore standard +// input should not be used by another entity. If Stdin() is set prior to this method +// being called, an error will be recorded as there are multiple entities trying to use +// the single standard input stream. +func (b *Builder) StdinInUse() *Builder { + if b.stdinInUse { + b.errs = append(b.errs, StdinMultiUseError) + } + b.stdinInUse = true + return b +} + // Stream will read objects from the provided reader, and if an error occurs will // include the name string in the error message. If ContinueOnError() is set // prior to this method being called, objects in the stream that are unrecognized @@ -911,9 +932,9 @@ func (b *Builder) getClient(gv schema.GroupVersion) (RESTClient, error) { case b.fakeClientFn != nil: client, err = b.fakeClientFn(gv) case b.negotiatedSerializer != nil: - client, err = b.clientConfigFn.clientForGroupVersion(gv, b.negotiatedSerializer) + client, err = b.clientConfigFn.withStdinUnavailable(b.stdinInUse).clientForGroupVersion(gv, b.negotiatedSerializer) default: - client, err = b.clientConfigFn.unstructuredClientForGroupVersion(gv) + client, err = b.clientConfigFn.withStdinUnavailable(b.stdinInUse).unstructuredClientForGroupVersion(gv) } if err != nil { diff --git a/vendor/k8s.io/cli-runtime/pkg/resource/client.go b/vendor/k8s.io/cli-runtime/pkg/resource/client.go index 46380207f..cd52c3043 100644 --- a/vendor/k8s.io/cli-runtime/pkg/resource/client.go +++ b/vendor/k8s.io/cli-runtime/pkg/resource/client.go @@ -56,3 +56,14 @@ func (clientConfigFn ClientConfigFunc) unstructuredClientForGroupVersion(gv sche return rest.RESTClientFor(cfg) } + +func (clientConfigFn ClientConfigFunc) withStdinUnavailable(stdinUnavailable bool) ClientConfigFunc { + return func() (*rest.Config, error) { + cfg, err := clientConfigFn() + if stdinUnavailable && cfg != nil && cfg.ExecProvider != nil { + cfg.ExecProvider.StdinUnavailable = stdinUnavailable + cfg.ExecProvider.StdinUnavailableMessage = "used by stdin resource manifest reader" + } + return cfg, err + } +} diff --git a/vendor/k8s.io/cli-runtime/pkg/resource/crd_finder.go b/vendor/k8s.io/cli-runtime/pkg/resource/crd_finder.go index 5dab3e46d..4694f7791 100644 --- a/vendor/k8s.io/cli-runtime/pkg/resource/crd_finder.go +++ b/vendor/k8s.io/cli-runtime/pkg/resource/crd_finder.go @@ -35,7 +35,7 @@ func CRDFromDynamic(client dynamic.Interface) CRDGetter { return func() ([]schema.GroupKind, error) { list, err := client.Resource(schema.GroupVersionResource{ Group: "apiextensions.k8s.io", - Version: "v1beta1", + Version: "v1", Resource: "customresourcedefinitions", }).List(context.TODO(), metav1.ListOptions{}) if err != nil { diff --git a/vendor/k8s.io/cli-runtime/pkg/resource/helper.go b/vendor/k8s.io/cli-runtime/pkg/resource/helper.go index 0132759d0..684802e88 100644 --- a/vendor/k8s.io/cli-runtime/pkg/resource/helper.go +++ b/vendor/k8s.io/cli-runtime/pkg/resource/helper.go @@ -18,9 +18,12 @@ package resource import ( "context" + "fmt" + apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" @@ -90,6 +93,54 @@ func (m *Helper) List(namespace, apiVersion string, options *metav1.ListOptions) return req.Do(context.TODO()).Get() } +// FollowContinue handles the continue parameter returned by the API server when using list +// chunking. To take advantage of this, the initial ListOptions provided by the consumer +// should include a non-zero Limit parameter. +func FollowContinue(initialOpts *metav1.ListOptions, + listFunc func(metav1.ListOptions) (runtime.Object, error)) error { + opts := initialOpts + for { + list, err := listFunc(*opts) + if err != nil { + return err + } + nextContinueToken, _ := metadataAccessor.Continue(list) + if len(nextContinueToken) == 0 { + return nil + } + opts.Continue = nextContinueToken + } +} + +// EnhanceListError augments errors typically returned by List operations with additional context, +// making sure to retain the StatusError type when applicable. +func EnhanceListError(err error, opts metav1.ListOptions, subj string) error { + if apierrors.IsResourceExpired(err) { + return err + } + if apierrors.IsBadRequest(err) || apierrors.IsNotFound(err) { + if se, ok := err.(*apierrors.StatusError); ok { + // modify the message without hiding this is an API error + if len(opts.LabelSelector) == 0 && len(opts.FieldSelector) == 0 { + se.ErrStatus.Message = fmt.Sprintf("Unable to list %q: %v", subj, + se.ErrStatus.Message) + } else { + se.ErrStatus.Message = fmt.Sprintf( + "Unable to find %q that match label selector %q, field selector %q: %v", subj, + opts.LabelSelector, + opts.FieldSelector, se.ErrStatus.Message) + } + return se + } + if len(opts.LabelSelector) == 0 && len(opts.FieldSelector) == 0 { + return fmt.Errorf("Unable to list %q: %v", subj, err) + } + return fmt.Errorf("Unable to find %q that match label selector %q, field selector %q: %v", + subj, opts.LabelSelector, opts.FieldSelector, err) + } + return err +} + func (m *Helper) Watch(namespace, apiVersion string, options *metav1.ListOptions) (watch.Interface, error) { options.Watch = true return m.RESTClient.Get(). diff --git a/vendor/k8s.io/cli-runtime/pkg/resource/kustomizevisitor.go b/vendor/k8s.io/cli-runtime/pkg/resource/kustomizevisitor.go index 22c9a548d..164891b88 100644 --- a/vendor/k8s.io/cli-runtime/pkg/resource/kustomizevisitor.go +++ b/vendor/k8s.io/cli-runtime/pkg/resource/kustomizevisitor.go @@ -19,8 +19,8 @@ package resource import ( "bytes" - "sigs.k8s.io/kustomize/api/filesys" "sigs.k8s.io/kustomize/api/krusty" + "sigs.k8s.io/kustomize/kyaml/filesys" ) // KustomizeVisitor handles kustomization.yaml files. diff --git a/vendor/k8s.io/cli-runtime/pkg/resource/selector.go b/vendor/k8s.io/cli-runtime/pkg/resource/selector.go index d29dfc46c..2a283d4e0 100644 --- a/vendor/k8s.io/cli-runtime/pkg/resource/selector.go +++ b/vendor/k8s.io/cli-runtime/pkg/resource/selector.go @@ -17,11 +17,9 @@ limitations under the License. package resource import ( - "fmt" - - "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/watch" ) @@ -49,41 +47,23 @@ func NewSelector(client RESTClient, mapping *meta.RESTMapping, namespace, labelS // Visit implements Visitor and uses request chunking by default. func (r *Selector) Visit(fn VisitorFunc) error { - var continueToken string - for { - list, err := NewHelper(r.Client, r.Mapping).List( + helper := NewHelper(r.Client, r.Mapping) + initialOpts := metav1.ListOptions{ + LabelSelector: r.LabelSelector, + FieldSelector: r.FieldSelector, + Limit: r.LimitChunks, + } + return FollowContinue(&initialOpts, func(options metav1.ListOptions) (runtime.Object, error) { + list, err := helper.List( r.Namespace, r.ResourceMapping().GroupVersionKind.GroupVersion().String(), - &metav1.ListOptions{ - LabelSelector: r.LabelSelector, - FieldSelector: r.FieldSelector, - Limit: r.LimitChunks, - Continue: continueToken, - }, + &options, ) if err != nil { - if errors.IsResourceExpired(err) { - return err - } - if errors.IsBadRequest(err) || errors.IsNotFound(err) { - if se, ok := err.(*errors.StatusError); ok { - // modify the message without hiding this is an API error - if len(r.LabelSelector) == 0 && len(r.FieldSelector) == 0 { - se.ErrStatus.Message = fmt.Sprintf("Unable to list %q: %v", r.Mapping.Resource, se.ErrStatus.Message) - } else { - se.ErrStatus.Message = fmt.Sprintf("Unable to find %q that match label selector %q, field selector %q: %v", r.Mapping.Resource, r.LabelSelector, r.FieldSelector, se.ErrStatus.Message) - } - return se - } - if len(r.LabelSelector) == 0 && len(r.FieldSelector) == 0 { - return fmt.Errorf("Unable to list %q: %v", r.Mapping.Resource, err) - } - return fmt.Errorf("Unable to find %q that match label selector %q, field selector %q: %v", r.Mapping.Resource, r.LabelSelector, r.FieldSelector, err) - } - return err + return nil, EnhanceListError(err, options, r.Mapping.Resource.String()) } resourceVersion, _ := metadataAccessor.ResourceVersion(list) - nextContinueToken, _ := metadataAccessor.Continue(list) + info := &Info{ Client: r.Client, Mapping: r.Mapping, @@ -95,13 +75,10 @@ func (r *Selector) Visit(fn VisitorFunc) error { } if err := fn(info, nil); err != nil { - return err + return nil, err } - if len(nextContinueToken) == 0 { - return nil - } - continueToken = nextContinueToken - } + return list, nil + }) } func (r *Selector) Watch(resourceVersion string) (watch.Interface, error) { diff --git a/vendor/k8s.io/klog/.travis.yml b/vendor/k8s.io/klog/.travis.yml deleted file mode 100644 index 5677664c2..000000000 --- a/vendor/k8s.io/klog/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -language: go -go_import_path: k8s.io/klog -dist: xenial -go: - - 1.9.x - - 1.10.x - - 1.11.x - - 1.12.x -script: - - go get -t -v ./... - - diff -u <(echo -n) <(gofmt -d .) - - diff -u <(echo -n) <(golint $(go list -e ./...)) - - go tool vet . || go vet . - - go test -v -race ./... -install: - - go get golang.org/x/lint/golint diff --git a/vendor/k8s.io/klog/CONTRIBUTING.md b/vendor/k8s.io/klog/CONTRIBUTING.md deleted file mode 100644 index 574a56abb..000000000 --- a/vendor/k8s.io/klog/CONTRIBUTING.md +++ /dev/null @@ -1,22 +0,0 @@ -# Contributing Guidelines - -Welcome to Kubernetes. We are excited about the prospect of you joining our [community](https://github.com/kubernetes/community)! The Kubernetes community abides by the CNCF [code of conduct](code-of-conduct.md). Here is an excerpt: - -_As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities._ - -## Getting Started - -We have full documentation on how to get started contributing here: - -- [Contributor License Agreement](https://git.k8s.io/community/CLA.md) Kubernetes projects require that you sign a Contributor License Agreement (CLA) before we can accept your pull requests -- [Kubernetes Contributor Guide](http://git.k8s.io/community/contributors/guide) - Main contributor documentation, or you can just jump directly to the [contributing section](http://git.k8s.io/community/contributors/guide#contributing) -- [Contributor Cheat Sheet](https://git.k8s.io/community/contributors/guide/contributor-cheatsheet.md) - Common resources for existing developers - -## Mentorship - -- [Mentoring Initiatives](https://git.k8s.io/community/mentoring) - We have a diverse set of mentorship programs available that are always looking for volunteers! - -## Contact Information - -- [Slack](https://kubernetes.slack.com/messages/sig-architecture) -- [Mailing List](https://groups.google.com/forum/#!forum/kubernetes-sig-architecture) diff --git a/vendor/k8s.io/klog/LICENSE b/vendor/k8s.io/klog/LICENSE deleted file mode 100644 index 37ec93a14..000000000 --- a/vendor/k8s.io/klog/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ -Apache License -Version 2.0, January 2004 -http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - -"License" shall mean the terms and conditions for use, reproduction, and -distribution as defined by Sections 1 through 9 of this document. - -"Licensor" shall mean the copyright owner or entity authorized by the copyright -owner that is granting the License. - -"Legal Entity" shall mean the union of the acting entity and all other entities -that control, are controlled by, or are under common control with that entity. -For the purposes of this definition, "control" means (i) the power, direct or -indirect, to cause the direction or management of such entity, whether by -contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the -outstanding shares, or (iii) beneficial ownership of such entity. - -"You" (or "Your") shall mean an individual or Legal Entity exercising -permissions granted by this License. - -"Source" form shall mean the preferred form for making modifications, including -but not limited to software source code, documentation source, and configuration -files. - -"Object" form shall mean any form resulting from mechanical transformation or -translation of a Source form, including but not limited to compiled object code, -generated documentation, and conversions to other media types. - -"Work" shall mean the work of authorship, whether in Source or Object form, made -available under the License, as indicated by a copyright notice that is included -in or attached to the work (an example is provided in the Appendix below). - -"Derivative Works" shall mean any work, whether in Source or Object form, that -is based on (or derived from) the Work and for which the editorial revisions, -annotations, elaborations, or other modifications represent, as a whole, an -original work of authorship. For the purposes of this License, Derivative Works -shall not include works that remain separable from, or merely link (or bind by -name) to the interfaces of, the Work and Derivative Works thereof. - -"Contribution" shall mean any work of authorship, including the original version -of the Work and any modifications or additions to that Work or Derivative Works -thereof, that is intentionally submitted to Licensor for inclusion in the Work -by the copyright owner or by an individual or Legal Entity authorized to submit -on behalf of the copyright owner. For the purposes of this definition, -"submitted" means any form of electronic, verbal, or written communication sent -to the Licensor or its representatives, including but not limited to -communication on electronic mailing lists, source code control systems, and -issue tracking systems that are managed by, or on behalf of, the Licensor for -the purpose of discussing and improving the Work, but excluding communication -that is conspicuously marked or otherwise designated in writing by the copyright -owner as "Not a Contribution." - -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf -of whom a Contribution has been received by Licensor and subsequently -incorporated within the Work. - -2. Grant of Copyright License. - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable copyright license to reproduce, prepare Derivative Works of, -publicly display, publicly perform, sublicense, and distribute the Work and such -Derivative Works in Source or Object form. - -3. Grant of Patent License. - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable (except as stated in this section) patent license to make, have -made, use, offer to sell, sell, import, and otherwise transfer the Work, where -such license applies only to those patent claims licensable by such Contributor -that are necessarily infringed by their Contribution(s) alone or by combination -of their Contribution(s) with the Work to which such Contribution(s) was -submitted. If You institute patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the Work or a -Contribution incorporated within the Work constitutes direct or contributory -patent infringement, then any patent licenses granted to You under this License -for that Work shall terminate as of the date such litigation is filed. - -4. Redistribution. - -You may reproduce and distribute copies of the Work or Derivative Works thereof -in any medium, with or without modifications, and in Source or Object form, -provided that You meet the following conditions: - -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -You must retain, in the Source form of any Derivative Works that You distribute, -all copyright, patent, trademark, and attribution notices from the Source form -of the Work, excluding those notices that do not pertain to any part of the -Derivative Works; and -If the Work includes a "NOTICE" text file as part of its distribution, then any -Derivative Works that You distribute must include a readable copy of the -attribution notices contained within such NOTICE file, excluding those notices -that do not pertain to any part of the Derivative Works, in at least one of the -following places: within a NOTICE text file distributed as part of the -Derivative Works; within the Source form or documentation, if provided along -with the Derivative Works; or, within a display generated by the Derivative -Works, if and wherever such third-party notices normally appear. The contents of -the NOTICE file are for informational purposes only and do not modify the -License. You may add Your own attribution notices within Derivative Works that -You distribute, alongside or as an addendum to the NOTICE text from the Work, -provided that such additional attribution notices cannot be construed as -modifying the License. -You may add Your own copyright statement to Your modifications and may provide -additional or different license terms and conditions for use, reproduction, or -distribution of Your modifications, or for any such Derivative Works as a whole, -provided Your use, reproduction, and distribution of the Work otherwise complies -with the conditions stated in this License. - -5. Submission of Contributions. - -Unless You explicitly state otherwise, any Contribution intentionally submitted -for inclusion in the Work by You to the Licensor shall be under the terms and -conditions of this License, without any additional terms or conditions. -Notwithstanding the above, nothing herein shall supersede or modify the terms of -any separate license agreement you may have executed with Licensor regarding -such Contributions. - -6. Trademarks. - -This License does not grant permission to use the trade names, trademarks, -service marks, or product names of the Licensor, except as required for -reasonable and customary use in describing the origin of the Work and -reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. - -Unless required by applicable law or agreed to in writing, Licensor provides the -Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, -including, without limitation, any warranties or conditions of TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are -solely responsible for determining the appropriateness of using or -redistributing the Work and assume any risks associated with Your exercise of -permissions under this License. - -8. Limitation of Liability. - -In no event and under no legal theory, whether in tort (including negligence), -contract, or otherwise, unless required by applicable law (such as deliberate -and grossly negligent acts) or agreed to in writing, shall any Contributor be -liable to You for damages, including any direct, indirect, special, incidental, -or consequential damages of any character arising as a result of this License or -out of the use or inability to use the Work (including but not limited to -damages for loss of goodwill, work stoppage, computer failure or malfunction, or -any and all other commercial damages or losses), even if such Contributor has -been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. - -While redistributing the Work or Derivative Works thereof, You may choose to -offer, and charge a fee for, acceptance of support, warranty, indemnity, or -other liability obligations and/or rights consistent with this License. However, -in accepting such obligations, You may act only on Your own behalf and on Your -sole responsibility, not on behalf of any other Contributor, and only if You -agree to indemnify, defend, and hold each Contributor harmless for any liability -incurred by, or claims asserted against, such Contributor by reason of your -accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work - -To apply the Apache License to your work, attach the following boilerplate -notice, with the fields enclosed by brackets "[]" replaced with your own -identifying information. (Don't include the brackets!) The text should be -enclosed in the appropriate comment syntax for the file format. We also -recommend that a file or class name and description of purpose be included on -the same "printed page" as the copyright notice for easier identification within -third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/k8s.io/klog/README.md b/vendor/k8s.io/klog/README.md deleted file mode 100644 index 841468b4b..000000000 --- a/vendor/k8s.io/klog/README.md +++ /dev/null @@ -1,97 +0,0 @@ -klog -==== - -klog is a permanent fork of https://github.com/golang/glog. - -## Why was klog created? - -The decision to create klog was one that wasn't made lightly, but it was necessary due to some -drawbacks that are present in [glog](https://github.com/golang/glog). Ultimately, the fork was created due to glog not being under active development; this can be seen in the glog README: - -> The code in this repo [...] is not itself under development - -This makes us unable to solve many use cases without a fork. The factors that contributed to needing feature development are listed below: - - * `glog` [presents a lot "gotchas"](https://github.com/kubernetes/kubernetes/issues/61006) and introduces challenges in containerized environments, all of which aren't well documented. - * `glog` doesn't provide an easy way to test logs, which detracts from the stability of software using it - * A long term goal is to implement a logging interface that allows us to add context, change output format, etc. - -Historical context is available here: - - * https://github.com/kubernetes/kubernetes/issues/61006 - * https://github.com/kubernetes/kubernetes/issues/70264 - * https://groups.google.com/forum/#!msg/kubernetes-sig-architecture/wCWiWf3Juzs/hXRVBH90CgAJ - * https://groups.google.com/forum/#!msg/kubernetes-dev/7vnijOMhLS0/1oRiNtigBgAJ - ----- - -How to use klog -=============== -- Replace imports for `github.com/golang/glog` with `k8s.io/klog` -- Use `klog.InitFlags(nil)` explicitly for initializing global flags as we no longer use `init()` method to register the flags -- You can now use `log-file` instead of `log-dir` for logging to a single file (See `examples/log_file/usage_log_file.go`) -- If you want to redirect everything logged using klog somewhere else (say syslog!), you can use `klog.SetOutput()` method and supply a `io.Writer`. (See `examples/set_output/usage_set_output.go`) -- For more logging conventions (See [Logging Conventions](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/logging.md)) - -### Coexisting with glog -This package can be used side by side with glog. [This example](examples/coexist_glog/coexist_glog.go) shows how to initialize and syncronize flags from the global `flag.CommandLine` FlagSet. In addition, the example makes use of stderr as combined output by setting `alsologtostderr` (or `logtostderr`) to `true`. - -## Community, discussion, contribution, and support - -Learn how to engage with the Kubernetes community on the [community page](http://kubernetes.io/community/). - -You can reach the maintainers of this project at: - -- [Slack](https://kubernetes.slack.com/messages/sig-architecture) -- [Mailing List](https://groups.google.com/forum/#!forum/kubernetes-sig-architecture) - -### Code of conduct - -Participation in the Kubernetes community is governed by the [Kubernetes Code of Conduct](code-of-conduct.md). - ----- - -glog -==== - -Leveled execution logs for Go. - -This is an efficient pure Go implementation of leveled logs in the -manner of the open source C++ package - https://github.com/google/glog - -By binding methods to booleans it is possible to use the log package -without paying the expense of evaluating the arguments to the log. -Through the -vmodule flag, the package also provides fine-grained -control over logging at the file level. - -The comment from glog.go introduces the ideas: - - Package glog implements logging analogous to the Google-internal - C++ INFO/ERROR/V setup. It provides functions Info, Warning, - Error, Fatal, plus formatting variants such as Infof. It - also provides V-style logging controlled by the -v and - -vmodule=file=2 flags. - - Basic examples: - - glog.Info("Prepare to repel boarders") - - glog.Fatalf("Initialization failed: %s", err) - - See the documentation for the V function for an explanation - of these examples: - - if glog.V(2) { - glog.Info("Starting transaction...") - } - - glog.V(2).Infoln("Processed", nItems, "elements") - - -The repository contains an open source version of the log package -used inside Google. The master copy of the source lives inside -Google, not here. The code in this repo is for export only and is not itself -under development. Feature requests will be ignored. - -Send bug reports to golang-nuts@googlegroups.com. diff --git a/vendor/k8s.io/klog/RELEASE.md b/vendor/k8s.io/klog/RELEASE.md deleted file mode 100644 index b53eb960c..000000000 --- a/vendor/k8s.io/klog/RELEASE.md +++ /dev/null @@ -1,9 +0,0 @@ -# Release Process - -The `klog` is released on an as-needed basis. The process is as follows: - -1. An issue is proposing a new release with a changelog since the last release -1. All [OWNERS](OWNERS) must LGTM this release -1. An OWNER runs `git tag -s $VERSION` and inserts the changelog and pushes the tag with `git push $VERSION` -1. The release issue is closed -1. An announcement email is sent to `kubernetes-dev@googlegroups.com` with the subject `[ANNOUNCE] kubernetes-template-project $VERSION is released` diff --git a/vendor/k8s.io/klog/SECURITY_CONTACTS b/vendor/k8s.io/klog/SECURITY_CONTACTS deleted file mode 100644 index 6128a5869..000000000 --- a/vendor/k8s.io/klog/SECURITY_CONTACTS +++ /dev/null @@ -1,20 +0,0 @@ -# Defined below are the security contacts for this repo. -# -# They are the contact point for the Product Security Committee to reach out -# to for triaging and handling of incoming issues. -# -# The below names agree to abide by the -# [Embargo Policy](https://git.k8s.io/security/private-distributors-list.md#embargo-policy) -# and will be removed and replaced if they violate that agreement. -# -# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE -# INSTRUCTIONS AT https://kubernetes.io/security/ - -dims -thockin -justinsb -tallclair -piosz -brancz -DirectXMan12 -lavalamp diff --git a/vendor/k8s.io/klog/code-of-conduct.md b/vendor/k8s.io/klog/code-of-conduct.md deleted file mode 100644 index 0d15c00cf..000000000 --- a/vendor/k8s.io/klog/code-of-conduct.md +++ /dev/null @@ -1,3 +0,0 @@ -# Kubernetes Community Code of Conduct - -Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md) diff --git a/vendor/k8s.io/klog/go.mod b/vendor/k8s.io/klog/go.mod deleted file mode 100644 index 3877d8546..000000000 --- a/vendor/k8s.io/klog/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module k8s.io/klog - -go 1.12 - -require github.com/go-logr/logr v0.1.0 diff --git a/vendor/k8s.io/klog/go.sum b/vendor/k8s.io/klog/go.sum deleted file mode 100644 index fb64d277a..000000000 --- a/vendor/k8s.io/klog/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/go-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= diff --git a/vendor/k8s.io/klog/klog.go b/vendor/k8s.io/klog/klog.go deleted file mode 100644 index 2712ce0af..000000000 --- a/vendor/k8s.io/klog/klog.go +++ /dev/null @@ -1,1308 +0,0 @@ -// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/ -// -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package klog implements logging analogous to the Google-internal C++ INFO/ERROR/V setup. -// It provides functions Info, Warning, Error, Fatal, plus formatting variants such as -// Infof. It also provides V-style logging controlled by the -v and -vmodule=file=2 flags. -// -// Basic examples: -// -// klog.Info("Prepare to repel boarders") -// -// klog.Fatalf("Initialization failed: %s", err) -// -// See the documentation for the V function for an explanation of these examples: -// -// if klog.V(2) { -// klog.Info("Starting transaction...") -// } -// -// klog.V(2).Infoln("Processed", nItems, "elements") -// -// Log output is buffered and written periodically using Flush. Programs -// should call Flush before exiting to guarantee all log output is written. -// -// By default, all log statements write to standard error. -// This package provides several flags that modify this behavior. -// As a result, flag.Parse must be called before any logging is done. -// -// -logtostderr=true -// Logs are written to standard error instead of to files. -// -alsologtostderr=false -// Logs are written to standard error as well as to files. -// -stderrthreshold=ERROR -// Log events at or above this severity are logged to standard -// error as well as to files. -// -log_dir="" -// Log files will be written to this directory instead of the -// default temporary directory. -// -// Other flags provide aids to debugging. -// -// -log_backtrace_at="" -// When set to a file and line number holding a logging statement, -// such as -// -log_backtrace_at=gopherflakes.go:234 -// a stack trace will be written to the Info log whenever execution -// hits that statement. (Unlike with -vmodule, the ".go" must be -// present.) -// -v=0 -// Enable V-leveled logging at the specified level. -// -vmodule="" -// The syntax of the argument is a comma-separated list of pattern=N, -// where pattern is a literal file name (minus the ".go" suffix) or -// "glob" pattern and N is a V level. For instance, -// -vmodule=gopher*=3 -// sets the V level to 3 in all Go files whose names begin "gopher". -// -package klog - -import ( - "bufio" - "bytes" - "errors" - "flag" - "fmt" - "io" - stdLog "log" - "math" - "os" - "path/filepath" - "runtime" - "strconv" - "strings" - "sync" - "sync/atomic" - "time" -) - -// severity identifies the sort of log: info, warning etc. It also implements -// the flag.Value interface. The -stderrthreshold flag is of type severity and -// should be modified only through the flag.Value interface. The values match -// the corresponding constants in C++. -type severity int32 // sync/atomic int32 - -// These constants identify the log levels in order of increasing severity. -// A message written to a high-severity log file is also written to each -// lower-severity log file. -const ( - infoLog severity = iota - warningLog - errorLog - fatalLog - numSeverity = 4 -) - -const severityChar = "IWEF" - -var severityName = []string{ - infoLog: "INFO", - warningLog: "WARNING", - errorLog: "ERROR", - fatalLog: "FATAL", -} - -// get returns the value of the severity. -func (s *severity) get() severity { - return severity(atomic.LoadInt32((*int32)(s))) -} - -// set sets the value of the severity. -func (s *severity) set(val severity) { - atomic.StoreInt32((*int32)(s), int32(val)) -} - -// String is part of the flag.Value interface. -func (s *severity) String() string { - return strconv.FormatInt(int64(*s), 10) -} - -// Get is part of the flag.Value interface. -func (s *severity) Get() interface{} { - return *s -} - -// Set is part of the flag.Value interface. -func (s *severity) Set(value string) error { - var threshold severity - // Is it a known name? - if v, ok := severityByName(value); ok { - threshold = v - } else { - v, err := strconv.ParseInt(value, 10, 32) - if err != nil { - return err - } - threshold = severity(v) - } - logging.stderrThreshold.set(threshold) - return nil -} - -func severityByName(s string) (severity, bool) { - s = strings.ToUpper(s) - for i, name := range severityName { - if name == s { - return severity(i), true - } - } - return 0, false -} - -// OutputStats tracks the number of output lines and bytes written. -type OutputStats struct { - lines int64 - bytes int64 -} - -// Lines returns the number of lines written. -func (s *OutputStats) Lines() int64 { - return atomic.LoadInt64(&s.lines) -} - -// Bytes returns the number of bytes written. -func (s *OutputStats) Bytes() int64 { - return atomic.LoadInt64(&s.bytes) -} - -// Stats tracks the number of lines of output and number of bytes -// per severity level. Values must be read with atomic.LoadInt64. -var Stats struct { - Info, Warning, Error OutputStats -} - -var severityStats = [numSeverity]*OutputStats{ - infoLog: &Stats.Info, - warningLog: &Stats.Warning, - errorLog: &Stats.Error, -} - -// Level is exported because it appears in the arguments to V and is -// the type of the v flag, which can be set programmatically. -// It's a distinct type because we want to discriminate it from logType. -// Variables of type level are only changed under logging.mu. -// The -v flag is read only with atomic ops, so the state of the logging -// module is consistent. - -// Level is treated as a sync/atomic int32. - -// Level specifies a level of verbosity for V logs. *Level implements -// flag.Value; the -v flag is of type Level and should be modified -// only through the flag.Value interface. -type Level int32 - -// get returns the value of the Level. -func (l *Level) get() Level { - return Level(atomic.LoadInt32((*int32)(l))) -} - -// set sets the value of the Level. -func (l *Level) set(val Level) { - atomic.StoreInt32((*int32)(l), int32(val)) -} - -// String is part of the flag.Value interface. -func (l *Level) String() string { - return strconv.FormatInt(int64(*l), 10) -} - -// Get is part of the flag.Value interface. -func (l *Level) Get() interface{} { - return *l -} - -// Set is part of the flag.Value interface. -func (l *Level) Set(value string) error { - v, err := strconv.ParseInt(value, 10, 32) - if err != nil { - return err - } - logging.mu.Lock() - defer logging.mu.Unlock() - logging.setVState(Level(v), logging.vmodule.filter, false) - return nil -} - -// moduleSpec represents the setting of the -vmodule flag. -type moduleSpec struct { - filter []modulePat -} - -// modulePat contains a filter for the -vmodule flag. -// It holds a verbosity level and a file pattern to match. -type modulePat struct { - pattern string - literal bool // The pattern is a literal string - level Level -} - -// match reports whether the file matches the pattern. It uses a string -// comparison if the pattern contains no metacharacters. -func (m *modulePat) match(file string) bool { - if m.literal { - return file == m.pattern - } - match, _ := filepath.Match(m.pattern, file) - return match -} - -func (m *moduleSpec) String() string { - // Lock because the type is not atomic. TODO: clean this up. - logging.mu.Lock() - defer logging.mu.Unlock() - var b bytes.Buffer - for i, f := range m.filter { - if i > 0 { - b.WriteRune(',') - } - fmt.Fprintf(&b, "%s=%d", f.pattern, f.level) - } - return b.String() -} - -// Get is part of the (Go 1.2) flag.Getter interface. It always returns nil for this flag type since the -// struct is not exported. -func (m *moduleSpec) Get() interface{} { - return nil -} - -var errVmoduleSyntax = errors.New("syntax error: expect comma-separated list of filename=N") - -// Syntax: -vmodule=recordio=2,file=1,gfs*=3 -func (m *moduleSpec) Set(value string) error { - var filter []modulePat - for _, pat := range strings.Split(value, ",") { - if len(pat) == 0 { - // Empty strings such as from a trailing comma can be ignored. - continue - } - patLev := strings.Split(pat, "=") - if len(patLev) != 2 || len(patLev[0]) == 0 || len(patLev[1]) == 0 { - return errVmoduleSyntax - } - pattern := patLev[0] - v, err := strconv.ParseInt(patLev[1], 10, 32) - if err != nil { - return errors.New("syntax error: expect comma-separated list of filename=N") - } - if v < 0 { - return errors.New("negative value for vmodule level") - } - if v == 0 { - continue // Ignore. It's harmless but no point in paying the overhead. - } - // TODO: check syntax of filter? - filter = append(filter, modulePat{pattern, isLiteral(pattern), Level(v)}) - } - logging.mu.Lock() - defer logging.mu.Unlock() - logging.setVState(logging.verbosity, filter, true) - return nil -} - -// isLiteral reports whether the pattern is a literal string, that is, has no metacharacters -// that require filepath.Match to be called to match the pattern. -func isLiteral(pattern string) bool { - return !strings.ContainsAny(pattern, `\*?[]`) -} - -// traceLocation represents the setting of the -log_backtrace_at flag. -type traceLocation struct { - file string - line int -} - -// isSet reports whether the trace location has been specified. -// logging.mu is held. -func (t *traceLocation) isSet() bool { - return t.line > 0 -} - -// match reports whether the specified file and line matches the trace location. -// The argument file name is the full path, not the basename specified in the flag. -// logging.mu is held. -func (t *traceLocation) match(file string, line int) bool { - if t.line != line { - return false - } - if i := strings.LastIndex(file, "/"); i >= 0 { - file = file[i+1:] - } - return t.file == file -} - -func (t *traceLocation) String() string { - // Lock because the type is not atomic. TODO: clean this up. - logging.mu.Lock() - defer logging.mu.Unlock() - return fmt.Sprintf("%s:%d", t.file, t.line) -} - -// Get is part of the (Go 1.2) flag.Getter interface. It always returns nil for this flag type since the -// struct is not exported -func (t *traceLocation) Get() interface{} { - return nil -} - -var errTraceSyntax = errors.New("syntax error: expect file.go:234") - -// Syntax: -log_backtrace_at=gopherflakes.go:234 -// Note that unlike vmodule the file extension is included here. -func (t *traceLocation) Set(value string) error { - if value == "" { - // Unset. - t.line = 0 - t.file = "" - } - fields := strings.Split(value, ":") - if len(fields) != 2 { - return errTraceSyntax - } - file, line := fields[0], fields[1] - if !strings.Contains(file, ".") { - return errTraceSyntax - } - v, err := strconv.Atoi(line) - if err != nil { - return errTraceSyntax - } - if v <= 0 { - return errors.New("negative or zero value for level") - } - logging.mu.Lock() - defer logging.mu.Unlock() - t.line = v - t.file = file - return nil -} - -// flushSyncWriter is the interface satisfied by logging destinations. -type flushSyncWriter interface { - Flush() error - Sync() error - io.Writer -} - -// init sets up the defaults and runs flushDaemon. -func init() { - logging.stderrThreshold = errorLog // Default stderrThreshold is ERROR. - logging.setVState(0, nil, false) - logging.logDir = "" - logging.logFile = "" - logging.logFileMaxSizeMB = 1800 - logging.toStderr = true - logging.alsoToStderr = false - logging.skipHeaders = false - logging.addDirHeader = false - logging.skipLogHeaders = false - go logging.flushDaemon() -} - -// InitFlags is for explicitly initializing the flags. -func InitFlags(flagset *flag.FlagSet) { - if flagset == nil { - flagset = flag.CommandLine - } - - flagset.StringVar(&logging.logDir, "log_dir", logging.logDir, "If non-empty, write log files in this directory") - flagset.StringVar(&logging.logFile, "log_file", logging.logFile, "If non-empty, use this log file") - flagset.Uint64Var(&logging.logFileMaxSizeMB, "log_file_max_size", logging.logFileMaxSizeMB, - "Defines the maximum size a log file can grow to. Unit is megabytes. "+ - "If the value is 0, the maximum file size is unlimited.") - flagset.BoolVar(&logging.toStderr, "logtostderr", logging.toStderr, "log to standard error instead of files") - flagset.BoolVar(&logging.alsoToStderr, "alsologtostderr", logging.alsoToStderr, "log to standard error as well as files") - flagset.Var(&logging.verbosity, "v", "number for the log level verbosity") - flagset.BoolVar(&logging.skipHeaders, "add_dir_header", logging.addDirHeader, "If true, adds the file directory to the header") - flagset.BoolVar(&logging.skipHeaders, "skip_headers", logging.skipHeaders, "If true, avoid header prefixes in the log messages") - flagset.BoolVar(&logging.skipLogHeaders, "skip_log_headers", logging.skipLogHeaders, "If true, avoid headers when opening log files") - flagset.Var(&logging.stderrThreshold, "stderrthreshold", "logs at or above this threshold go to stderr") - flagset.Var(&logging.vmodule, "vmodule", "comma-separated list of pattern=N settings for file-filtered logging") - flagset.Var(&logging.traceLocation, "log_backtrace_at", "when logging hits line file:N, emit a stack trace") -} - -// Flush flushes all pending log I/O. -func Flush() { - logging.lockAndFlushAll() -} - -// loggingT collects all the global state of the logging setup. -type loggingT struct { - // Boolean flags. Not handled atomically because the flag.Value interface - // does not let us avoid the =true, and that shorthand is necessary for - // compatibility. TODO: does this matter enough to fix? Seems unlikely. - toStderr bool // The -logtostderr flag. - alsoToStderr bool // The -alsologtostderr flag. - - // Level flag. Handled atomically. - stderrThreshold severity // The -stderrthreshold flag. - - // freeList is a list of byte buffers, maintained under freeListMu. - freeList *buffer - // freeListMu maintains the free list. It is separate from the main mutex - // so buffers can be grabbed and printed to without holding the main lock, - // for better parallelization. - freeListMu sync.Mutex - - // mu protects the remaining elements of this structure and is - // used to synchronize logging. - mu sync.Mutex - // file holds writer for each of the log types. - file [numSeverity]flushSyncWriter - // pcs is used in V to avoid an allocation when computing the caller's PC. - pcs [1]uintptr - // vmap is a cache of the V Level for each V() call site, identified by PC. - // It is wiped whenever the vmodule flag changes state. - vmap map[uintptr]Level - // filterLength stores the length of the vmodule filter chain. If greater - // than zero, it means vmodule is enabled. It may be read safely - // using sync.LoadInt32, but is only modified under mu. - filterLength int32 - // traceLocation is the state of the -log_backtrace_at flag. - traceLocation traceLocation - // These flags are modified only under lock, although verbosity may be fetched - // safely using atomic.LoadInt32. - vmodule moduleSpec // The state of the -vmodule flag. - verbosity Level // V logging level, the value of the -v flag/ - - // If non-empty, overrides the choice of directory in which to write logs. - // See createLogDirs for the full list of possible destinations. - logDir string - - // If non-empty, specifies the path of the file to write logs. mutually exclusive - // with the log-dir option. - logFile string - - // When logFile is specified, this limiter makes sure the logFile won't exceeds a certain size. When exceeds, the - // logFile will be cleaned up. If this value is 0, no size limitation will be applied to logFile. - logFileMaxSizeMB uint64 - - // If true, do not add the prefix headers, useful when used with SetOutput - skipHeaders bool - - // If true, do not add the headers to log files - skipLogHeaders bool - - // If true, add the file directory to the header - addDirHeader bool -} - -// buffer holds a byte Buffer for reuse. The zero value is ready for use. -type buffer struct { - bytes.Buffer - tmp [64]byte // temporary byte array for creating headers. - next *buffer -} - -var logging loggingT - -// setVState sets a consistent state for V logging. -// l.mu is held. -func (l *loggingT) setVState(verbosity Level, filter []modulePat, setFilter bool) { - // Turn verbosity off so V will not fire while we are in transition. - logging.verbosity.set(0) - // Ditto for filter length. - atomic.StoreInt32(&logging.filterLength, 0) - - // Set the new filters and wipe the pc->Level map if the filter has changed. - if setFilter { - logging.vmodule.filter = filter - logging.vmap = make(map[uintptr]Level) - } - - // Things are consistent now, so enable filtering and verbosity. - // They are enabled in order opposite to that in V. - atomic.StoreInt32(&logging.filterLength, int32(len(filter))) - logging.verbosity.set(verbosity) -} - -// getBuffer returns a new, ready-to-use buffer. -func (l *loggingT) getBuffer() *buffer { - l.freeListMu.Lock() - b := l.freeList - if b != nil { - l.freeList = b.next - } - l.freeListMu.Unlock() - if b == nil { - b = new(buffer) - } else { - b.next = nil - b.Reset() - } - return b -} - -// putBuffer returns a buffer to the free list. -func (l *loggingT) putBuffer(b *buffer) { - if b.Len() >= 256 { - // Let big buffers die a natural death. - return - } - l.freeListMu.Lock() - b.next = l.freeList - l.freeList = b - l.freeListMu.Unlock() -} - -var timeNow = time.Now // Stubbed out for testing. - -/* -header formats a log header as defined by the C++ implementation. -It returns a buffer containing the formatted header and the user's file and line number. -The depth specifies how many stack frames above lives the source line to be identified in the log message. - -Log lines have this form: - Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg... -where the fields are defined as follows: - L A single character, representing the log level (eg 'I' for INFO) - mm The month (zero padded; ie May is '05') - dd The day (zero padded) - hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds - threadid The space-padded thread ID as returned by GetTID() - file The file name - line The line number - msg The user-supplied message -*/ -func (l *loggingT) header(s severity, depth int) (*buffer, string, int) { - _, file, line, ok := runtime.Caller(3 + depth) - if !ok { - file = "???" - line = 1 - } else { - if slash := strings.LastIndex(file, "/"); slash >= 0 { - path := file - file = path[slash+1:] - if l.addDirHeader { - if dirsep := strings.LastIndex(path[:slash], "/"); dirsep >= 0 { - file = path[dirsep+1:] - } - } - } - } - return l.formatHeader(s, file, line), file, line -} - -// formatHeader formats a log header using the provided file name and line number. -func (l *loggingT) formatHeader(s severity, file string, line int) *buffer { - now := timeNow() - if line < 0 { - line = 0 // not a real line number, but acceptable to someDigits - } - if s > fatalLog { - s = infoLog // for safety. - } - buf := l.getBuffer() - if l.skipHeaders { - return buf - } - - // Avoid Fprintf, for speed. The format is so simple that we can do it quickly by hand. - // It's worth about 3X. Fprintf is hard. - _, month, day := now.Date() - hour, minute, second := now.Clock() - // Lmmdd hh:mm:ss.uuuuuu threadid file:line] - buf.tmp[0] = severityChar[s] - buf.twoDigits(1, int(month)) - buf.twoDigits(3, day) - buf.tmp[5] = ' ' - buf.twoDigits(6, hour) - buf.tmp[8] = ':' - buf.twoDigits(9, minute) - buf.tmp[11] = ':' - buf.twoDigits(12, second) - buf.tmp[14] = '.' - buf.nDigits(6, 15, now.Nanosecond()/1000, '0') - buf.tmp[21] = ' ' - buf.nDigits(7, 22, pid, ' ') // TODO: should be TID - buf.tmp[29] = ' ' - buf.Write(buf.tmp[:30]) - buf.WriteString(file) - buf.tmp[0] = ':' - n := buf.someDigits(1, line) - buf.tmp[n+1] = ']' - buf.tmp[n+2] = ' ' - buf.Write(buf.tmp[:n+3]) - return buf -} - -// Some custom tiny helper functions to print the log header efficiently. - -const digits = "0123456789" - -// twoDigits formats a zero-prefixed two-digit integer at buf.tmp[i]. -func (buf *buffer) twoDigits(i, d int) { - buf.tmp[i+1] = digits[d%10] - d /= 10 - buf.tmp[i] = digits[d%10] -} - -// nDigits formats an n-digit integer at buf.tmp[i], -// padding with pad on the left. -// It assumes d >= 0. -func (buf *buffer) nDigits(n, i, d int, pad byte) { - j := n - 1 - for ; j >= 0 && d > 0; j-- { - buf.tmp[i+j] = digits[d%10] - d /= 10 - } - for ; j >= 0; j-- { - buf.tmp[i+j] = pad - } -} - -// someDigits formats a zero-prefixed variable-width integer at buf.tmp[i]. -func (buf *buffer) someDigits(i, d int) int { - // Print into the top, then copy down. We know there's space for at least - // a 10-digit number. - j := len(buf.tmp) - for { - j-- - buf.tmp[j] = digits[d%10] - d /= 10 - if d == 0 { - break - } - } - return copy(buf.tmp[i:], buf.tmp[j:]) -} - -func (l *loggingT) println(s severity, args ...interface{}) { - buf, file, line := l.header(s, 0) - fmt.Fprintln(buf, args...) - l.output(s, buf, file, line, false) -} - -func (l *loggingT) print(s severity, args ...interface{}) { - l.printDepth(s, 1, args...) -} - -func (l *loggingT) printDepth(s severity, depth int, args ...interface{}) { - buf, file, line := l.header(s, depth) - fmt.Fprint(buf, args...) - if buf.Bytes()[buf.Len()-1] != '\n' { - buf.WriteByte('\n') - } - l.output(s, buf, file, line, false) -} - -func (l *loggingT) printf(s severity, format string, args ...interface{}) { - buf, file, line := l.header(s, 0) - fmt.Fprintf(buf, format, args...) - if buf.Bytes()[buf.Len()-1] != '\n' { - buf.WriteByte('\n') - } - l.output(s, buf, file, line, false) -} - -// printWithFileLine behaves like print but uses the provided file and line number. If -// alsoLogToStderr is true, the log message always appears on standard error; it -// will also appear in the log file unless --logtostderr is set. -func (l *loggingT) printWithFileLine(s severity, file string, line int, alsoToStderr bool, args ...interface{}) { - buf := l.formatHeader(s, file, line) - fmt.Fprint(buf, args...) - if buf.Bytes()[buf.Len()-1] != '\n' { - buf.WriteByte('\n') - } - l.output(s, buf, file, line, alsoToStderr) -} - -// redirectBuffer is used to set an alternate destination for the logs -type redirectBuffer struct { - w io.Writer -} - -func (rb *redirectBuffer) Sync() error { - return nil -} - -func (rb *redirectBuffer) Flush() error { - return nil -} - -func (rb *redirectBuffer) Write(bytes []byte) (n int, err error) { - return rb.w.Write(bytes) -} - -// SetOutput sets the output destination for all severities -func SetOutput(w io.Writer) { - logging.mu.Lock() - defer logging.mu.Unlock() - for s := fatalLog; s >= infoLog; s-- { - rb := &redirectBuffer{ - w: w, - } - logging.file[s] = rb - } -} - -// SetOutputBySeverity sets the output destination for specific severity -func SetOutputBySeverity(name string, w io.Writer) { - logging.mu.Lock() - defer logging.mu.Unlock() - sev, ok := severityByName(name) - if !ok { - panic(fmt.Sprintf("SetOutputBySeverity(%q): unrecognized severity name", name)) - } - rb := &redirectBuffer{ - w: w, - } - logging.file[sev] = rb -} - -// output writes the data to the log files and releases the buffer. -func (l *loggingT) output(s severity, buf *buffer, file string, line int, alsoToStderr bool) { - l.mu.Lock() - if l.traceLocation.isSet() { - if l.traceLocation.match(file, line) { - buf.Write(stacks(false)) - } - } - data := buf.Bytes() - if l.toStderr { - os.Stderr.Write(data) - } else { - if alsoToStderr || l.alsoToStderr || s >= l.stderrThreshold.get() { - os.Stderr.Write(data) - } - - if logging.logFile != "" { - // Since we are using a single log file, all of the items in l.file array - // will point to the same file, so just use one of them to write data. - if l.file[infoLog] == nil { - if err := l.createFiles(infoLog); err != nil { - os.Stderr.Write(data) // Make sure the message appears somewhere. - l.exit(err) - } - } - l.file[infoLog].Write(data) - } else { - if l.file[s] == nil { - if err := l.createFiles(s); err != nil { - os.Stderr.Write(data) // Make sure the message appears somewhere. - l.exit(err) - } - } - - switch s { - case fatalLog: - l.file[fatalLog].Write(data) - fallthrough - case errorLog: - l.file[errorLog].Write(data) - fallthrough - case warningLog: - l.file[warningLog].Write(data) - fallthrough - case infoLog: - l.file[infoLog].Write(data) - } - } - } - if s == fatalLog { - // If we got here via Exit rather than Fatal, print no stacks. - if atomic.LoadUint32(&fatalNoStacks) > 0 { - l.mu.Unlock() - timeoutFlush(10 * time.Second) - os.Exit(1) - } - // Dump all goroutine stacks before exiting. - // First, make sure we see the trace for the current goroutine on standard error. - // If -logtostderr has been specified, the loop below will do that anyway - // as the first stack in the full dump. - if !l.toStderr { - os.Stderr.Write(stacks(false)) - } - // Write the stack trace for all goroutines to the files. - trace := stacks(true) - logExitFunc = func(error) {} // If we get a write error, we'll still exit below. - for log := fatalLog; log >= infoLog; log-- { - if f := l.file[log]; f != nil { // Can be nil if -logtostderr is set. - f.Write(trace) - } - } - l.mu.Unlock() - timeoutFlush(10 * time.Second) - os.Exit(255) // C++ uses -1, which is silly because it's anded with 255 anyway. - } - l.putBuffer(buf) - l.mu.Unlock() - if stats := severityStats[s]; stats != nil { - atomic.AddInt64(&stats.lines, 1) - atomic.AddInt64(&stats.bytes, int64(len(data))) - } -} - -// timeoutFlush calls Flush and returns when it completes or after timeout -// elapses, whichever happens first. This is needed because the hooks invoked -// by Flush may deadlock when klog.Fatal is called from a hook that holds -// a lock. -func timeoutFlush(timeout time.Duration) { - done := make(chan bool, 1) - go func() { - Flush() // calls logging.lockAndFlushAll() - done <- true - }() - select { - case <-done: - case <-time.After(timeout): - fmt.Fprintln(os.Stderr, "klog: Flush took longer than", timeout) - } -} - -// stacks is a wrapper for runtime.Stack that attempts to recover the data for all goroutines. -func stacks(all bool) []byte { - // We don't know how big the traces are, so grow a few times if they don't fit. Start large, though. - n := 10000 - if all { - n = 100000 - } - var trace []byte - for i := 0; i < 5; i++ { - trace = make([]byte, n) - nbytes := runtime.Stack(trace, all) - if nbytes < len(trace) { - return trace[:nbytes] - } - n *= 2 - } - return trace -} - -// logExitFunc provides a simple mechanism to override the default behavior -// of exiting on error. Used in testing and to guarantee we reach a required exit -// for fatal logs. Instead, exit could be a function rather than a method but that -// would make its use clumsier. -var logExitFunc func(error) - -// exit is called if there is trouble creating or writing log files. -// It flushes the logs and exits the program; there's no point in hanging around. -// l.mu is held. -func (l *loggingT) exit(err error) { - fmt.Fprintf(os.Stderr, "log: exiting because of error: %s\n", err) - // If logExitFunc is set, we do that instead of exiting. - if logExitFunc != nil { - logExitFunc(err) - return - } - l.flushAll() - os.Exit(2) -} - -// syncBuffer joins a bufio.Writer to its underlying file, providing access to the -// file's Sync method and providing a wrapper for the Write method that provides log -// file rotation. There are conflicting methods, so the file cannot be embedded. -// l.mu is held for all its methods. -type syncBuffer struct { - logger *loggingT - *bufio.Writer - file *os.File - sev severity - nbytes uint64 // The number of bytes written to this file - maxbytes uint64 // The max number of bytes this syncBuffer.file can hold before cleaning up. -} - -func (sb *syncBuffer) Sync() error { - return sb.file.Sync() -} - -// CalculateMaxSize returns the real max size in bytes after considering the default max size and the flag options. -func CalculateMaxSize() uint64 { - if logging.logFile != "" { - if logging.logFileMaxSizeMB == 0 { - // If logFileMaxSizeMB is zero, we don't have limitations on the log size. - return math.MaxUint64 - } - // Flag logFileMaxSizeMB is in MB for user convenience. - return logging.logFileMaxSizeMB * 1024 * 1024 - } - // If "log_file" flag is not specified, the target file (sb.file) will be cleaned up when reaches a fixed size. - return MaxSize -} - -func (sb *syncBuffer) Write(p []byte) (n int, err error) { - if sb.nbytes+uint64(len(p)) >= sb.maxbytes { - if err := sb.rotateFile(time.Now(), false); err != nil { - sb.logger.exit(err) - } - } - n, err = sb.Writer.Write(p) - sb.nbytes += uint64(n) - if err != nil { - sb.logger.exit(err) - } - return -} - -// rotateFile closes the syncBuffer's file and starts a new one. -// The startup argument indicates whether this is the initial startup of klog. -// If startup is true, existing files are opened for appending instead of truncated. -func (sb *syncBuffer) rotateFile(now time.Time, startup bool) error { - if sb.file != nil { - sb.Flush() - sb.file.Close() - } - var err error - sb.file, _, err = create(severityName[sb.sev], now, startup) - sb.nbytes = 0 - if err != nil { - return err - } - - sb.Writer = bufio.NewWriterSize(sb.file, bufferSize) - - if sb.logger.skipLogHeaders { - return nil - } - - // Write header. - var buf bytes.Buffer - fmt.Fprintf(&buf, "Log file created at: %s\n", now.Format("2006/01/02 15:04:05")) - fmt.Fprintf(&buf, "Running on machine: %s\n", host) - fmt.Fprintf(&buf, "Binary: Built with %s %s for %s/%s\n", runtime.Compiler, runtime.Version(), runtime.GOOS, runtime.GOARCH) - fmt.Fprintf(&buf, "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg\n") - n, err := sb.file.Write(buf.Bytes()) - sb.nbytes += uint64(n) - return err -} - -// bufferSize sizes the buffer associated with each log file. It's large -// so that log records can accumulate without the logging thread blocking -// on disk I/O. The flushDaemon will block instead. -const bufferSize = 256 * 1024 - -// createFiles creates all the log files for severity from sev down to infoLog. -// l.mu is held. -func (l *loggingT) createFiles(sev severity) error { - now := time.Now() - // Files are created in decreasing severity order, so as soon as we find one - // has already been created, we can stop. - for s := sev; s >= infoLog && l.file[s] == nil; s-- { - sb := &syncBuffer{ - logger: l, - sev: s, - maxbytes: CalculateMaxSize(), - } - if err := sb.rotateFile(now, true); err != nil { - return err - } - l.file[s] = sb - } - return nil -} - -const flushInterval = 5 * time.Second - -// flushDaemon periodically flushes the log file buffers. -func (l *loggingT) flushDaemon() { - for range time.NewTicker(flushInterval).C { - l.lockAndFlushAll() - } -} - -// lockAndFlushAll is like flushAll but locks l.mu first. -func (l *loggingT) lockAndFlushAll() { - l.mu.Lock() - l.flushAll() - l.mu.Unlock() -} - -// flushAll flushes all the logs and attempts to "sync" their data to disk. -// l.mu is held. -func (l *loggingT) flushAll() { - // Flush from fatal down, in case there's trouble flushing. - for s := fatalLog; s >= infoLog; s-- { - file := l.file[s] - if file != nil { - file.Flush() // ignore error - file.Sync() // ignore error - } - } -} - -// CopyStandardLogTo arranges for messages written to the Go "log" package's -// default logs to also appear in the Google logs for the named and lower -// severities. Subsequent changes to the standard log's default output location -// or format may break this behavior. -// -// Valid names are "INFO", "WARNING", "ERROR", and "FATAL". If the name is not -// recognized, CopyStandardLogTo panics. -func CopyStandardLogTo(name string) { - sev, ok := severityByName(name) - if !ok { - panic(fmt.Sprintf("log.CopyStandardLogTo(%q): unrecognized severity name", name)) - } - // Set a log format that captures the user's file and line: - // d.go:23: message - stdLog.SetFlags(stdLog.Lshortfile) - stdLog.SetOutput(logBridge(sev)) -} - -// logBridge provides the Write method that enables CopyStandardLogTo to connect -// Go's standard logs to the logs provided by this package. -type logBridge severity - -// Write parses the standard logging line and passes its components to the -// logger for severity(lb). -func (lb logBridge) Write(b []byte) (n int, err error) { - var ( - file = "???" - line = 1 - text string - ) - // Split "d.go:23: message" into "d.go", "23", and "message". - if parts := bytes.SplitN(b, []byte{':'}, 3); len(parts) != 3 || len(parts[0]) < 1 || len(parts[2]) < 1 { - text = fmt.Sprintf("bad log format: %s", b) - } else { - file = string(parts[0]) - text = string(parts[2][1:]) // skip leading space - line, err = strconv.Atoi(string(parts[1])) - if err != nil { - text = fmt.Sprintf("bad line number: %s", b) - line = 1 - } - } - // printWithFileLine with alsoToStderr=true, so standard log messages - // always appear on standard error. - logging.printWithFileLine(severity(lb), file, line, true, text) - return len(b), nil -} - -// setV computes and remembers the V level for a given PC -// when vmodule is enabled. -// File pattern matching takes the basename of the file, stripped -// of its .go suffix, and uses filepath.Match, which is a little more -// general than the *? matching used in C++. -// l.mu is held. -func (l *loggingT) setV(pc uintptr) Level { - fn := runtime.FuncForPC(pc) - file, _ := fn.FileLine(pc) - // The file is something like /a/b/c/d.go. We want just the d. - if strings.HasSuffix(file, ".go") { - file = file[:len(file)-3] - } - if slash := strings.LastIndex(file, "/"); slash >= 0 { - file = file[slash+1:] - } - for _, filter := range l.vmodule.filter { - if filter.match(file) { - l.vmap[pc] = filter.level - return filter.level - } - } - l.vmap[pc] = 0 - return 0 -} - -// Verbose is a boolean type that implements Infof (like Printf) etc. -// See the documentation of V for more information. -type Verbose bool - -// V reports whether verbosity at the call site is at least the requested level. -// The returned value is a boolean of type Verbose, which implements Info, Infoln -// and Infof. These methods will write to the Info log if called. -// Thus, one may write either -// if klog.V(2) { klog.Info("log this") } -// or -// klog.V(2).Info("log this") -// The second form is shorter but the first is cheaper if logging is off because it does -// not evaluate its arguments. -// -// Whether an individual call to V generates a log record depends on the setting of -// the -v and --vmodule flags; both are off by default. If the level in the call to -// V is at least the value of -v, or of -vmodule for the source file containing the -// call, the V call will log. -func V(level Level) Verbose { - // This function tries hard to be cheap unless there's work to do. - // The fast path is two atomic loads and compares. - - // Here is a cheap but safe test to see if V logging is enabled globally. - if logging.verbosity.get() >= level { - return Verbose(true) - } - - // It's off globally but it vmodule may still be set. - // Here is another cheap but safe test to see if vmodule is enabled. - if atomic.LoadInt32(&logging.filterLength) > 0 { - // Now we need a proper lock to use the logging structure. The pcs field - // is shared so we must lock before accessing it. This is fairly expensive, - // but if V logging is enabled we're slow anyway. - logging.mu.Lock() - defer logging.mu.Unlock() - if runtime.Callers(2, logging.pcs[:]) == 0 { - return Verbose(false) - } - v, ok := logging.vmap[logging.pcs[0]] - if !ok { - v = logging.setV(logging.pcs[0]) - } - return Verbose(v >= level) - } - return Verbose(false) -} - -// Info is equivalent to the global Info function, guarded by the value of v. -// See the documentation of V for usage. -func (v Verbose) Info(args ...interface{}) { - if v { - logging.print(infoLog, args...) - } -} - -// Infoln is equivalent to the global Infoln function, guarded by the value of v. -// See the documentation of V for usage. -func (v Verbose) Infoln(args ...interface{}) { - if v { - logging.println(infoLog, args...) - } -} - -// Infof is equivalent to the global Infof function, guarded by the value of v. -// See the documentation of V for usage. -func (v Verbose) Infof(format string, args ...interface{}) { - if v { - logging.printf(infoLog, format, args...) - } -} - -// Info logs to the INFO log. -// Arguments are handled in the manner of fmt.Print; a newline is appended if missing. -func Info(args ...interface{}) { - logging.print(infoLog, args...) -} - -// InfoDepth acts as Info but uses depth to determine which call frame to log. -// InfoDepth(0, "msg") is the same as Info("msg"). -func InfoDepth(depth int, args ...interface{}) { - logging.printDepth(infoLog, depth, args...) -} - -// Infoln logs to the INFO log. -// Arguments are handled in the manner of fmt.Println; a newline is always appended. -func Infoln(args ...interface{}) { - logging.println(infoLog, args...) -} - -// Infof logs to the INFO log. -// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. -func Infof(format string, args ...interface{}) { - logging.printf(infoLog, format, args...) -} - -// Warning logs to the WARNING and INFO logs. -// Arguments are handled in the manner of fmt.Print; a newline is appended if missing. -func Warning(args ...interface{}) { - logging.print(warningLog, args...) -} - -// WarningDepth acts as Warning but uses depth to determine which call frame to log. -// WarningDepth(0, "msg") is the same as Warning("msg"). -func WarningDepth(depth int, args ...interface{}) { - logging.printDepth(warningLog, depth, args...) -} - -// Warningln logs to the WARNING and INFO logs. -// Arguments are handled in the manner of fmt.Println; a newline is always appended. -func Warningln(args ...interface{}) { - logging.println(warningLog, args...) -} - -// Warningf logs to the WARNING and INFO logs. -// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. -func Warningf(format string, args ...interface{}) { - logging.printf(warningLog, format, args...) -} - -// Error logs to the ERROR, WARNING, and INFO logs. -// Arguments are handled in the manner of fmt.Print; a newline is appended if missing. -func Error(args ...interface{}) { - logging.print(errorLog, args...) -} - -// ErrorDepth acts as Error but uses depth to determine which call frame to log. -// ErrorDepth(0, "msg") is the same as Error("msg"). -func ErrorDepth(depth int, args ...interface{}) { - logging.printDepth(errorLog, depth, args...) -} - -// Errorln logs to the ERROR, WARNING, and INFO logs. -// Arguments are handled in the manner of fmt.Println; a newline is always appended. -func Errorln(args ...interface{}) { - logging.println(errorLog, args...) -} - -// Errorf logs to the ERROR, WARNING, and INFO logs. -// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. -func Errorf(format string, args ...interface{}) { - logging.printf(errorLog, format, args...) -} - -// Fatal logs to the FATAL, ERROR, WARNING, and INFO logs, -// including a stack trace of all running goroutines, then calls os.Exit(255). -// Arguments are handled in the manner of fmt.Print; a newline is appended if missing. -func Fatal(args ...interface{}) { - logging.print(fatalLog, args...) -} - -// FatalDepth acts as Fatal but uses depth to determine which call frame to log. -// FatalDepth(0, "msg") is the same as Fatal("msg"). -func FatalDepth(depth int, args ...interface{}) { - logging.printDepth(fatalLog, depth, args...) -} - -// Fatalln logs to the FATAL, ERROR, WARNING, and INFO logs, -// including a stack trace of all running goroutines, then calls os.Exit(255). -// Arguments are handled in the manner of fmt.Println; a newline is always appended. -func Fatalln(args ...interface{}) { - logging.println(fatalLog, args...) -} - -// Fatalf logs to the FATAL, ERROR, WARNING, and INFO logs, -// including a stack trace of all running goroutines, then calls os.Exit(255). -// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. -func Fatalf(format string, args ...interface{}) { - logging.printf(fatalLog, format, args...) -} - -// fatalNoStacks is non-zero if we are to exit without dumping goroutine stacks. -// It allows Exit and relatives to use the Fatal logs. -var fatalNoStacks uint32 - -// Exit logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1). -// Arguments are handled in the manner of fmt.Print; a newline is appended if missing. -func Exit(args ...interface{}) { - atomic.StoreUint32(&fatalNoStacks, 1) - logging.print(fatalLog, args...) -} - -// ExitDepth acts as Exit but uses depth to determine which call frame to log. -// ExitDepth(0, "msg") is the same as Exit("msg"). -func ExitDepth(depth int, args ...interface{}) { - atomic.StoreUint32(&fatalNoStacks, 1) - logging.printDepth(fatalLog, depth, args...) -} - -// Exitln logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1). -func Exitln(args ...interface{}) { - atomic.StoreUint32(&fatalNoStacks, 1) - logging.println(fatalLog, args...) -} - -// Exitf logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1). -// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. -func Exitf(format string, args ...interface{}) { - atomic.StoreUint32(&fatalNoStacks, 1) - logging.printf(fatalLog, format, args...) -} diff --git a/vendor/k8s.io/klog/klog_file.go b/vendor/k8s.io/klog/klog_file.go deleted file mode 100644 index e4010ad4d..000000000 --- a/vendor/k8s.io/klog/klog_file.go +++ /dev/null @@ -1,139 +0,0 @@ -// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/ -// -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// File I/O for logs. - -package klog - -import ( - "errors" - "fmt" - "os" - "os/user" - "path/filepath" - "strings" - "sync" - "time" -) - -// MaxSize is the maximum size of a log file in bytes. -var MaxSize uint64 = 1024 * 1024 * 1800 - -// logDirs lists the candidate directories for new log files. -var logDirs []string - -func createLogDirs() { - if logging.logDir != "" { - logDirs = append(logDirs, logging.logDir) - } - logDirs = append(logDirs, os.TempDir()) -} - -var ( - pid = os.Getpid() - program = filepath.Base(os.Args[0]) - host = "unknownhost" - userName = "unknownuser" -) - -func init() { - h, err := os.Hostname() - if err == nil { - host = shortHostname(h) - } - - current, err := user.Current() - if err == nil { - userName = current.Username - } - - // Sanitize userName since it may contain filepath separators on Windows. - userName = strings.Replace(userName, `\`, "_", -1) -} - -// shortHostname returns its argument, truncating at the first period. -// For instance, given "www.google.com" it returns "www". -func shortHostname(hostname string) string { - if i := strings.Index(hostname, "."); i >= 0 { - return hostname[:i] - } - return hostname -} - -// logName returns a new log file name containing tag, with start time t, and -// the name for the symlink for tag. -func logName(tag string, t time.Time) (name, link string) { - name = fmt.Sprintf("%s.%s.%s.log.%s.%04d%02d%02d-%02d%02d%02d.%d", - program, - host, - userName, - tag, - t.Year(), - t.Month(), - t.Day(), - t.Hour(), - t.Minute(), - t.Second(), - pid) - return name, program + "." + tag -} - -var onceLogDirs sync.Once - -// create creates a new log file and returns the file and its filename, which -// contains tag ("INFO", "FATAL", etc.) and t. If the file is created -// successfully, create also attempts to update the symlink for that tag, ignoring -// errors. -// The startup argument indicates whether this is the initial startup of klog. -// If startup is true, existing files are opened for appending instead of truncated. -func create(tag string, t time.Time, startup bool) (f *os.File, filename string, err error) { - if logging.logFile != "" { - f, err := openOrCreate(logging.logFile, startup) - if err == nil { - return f, logging.logFile, nil - } - return nil, "", fmt.Errorf("log: unable to create log: %v", err) - } - onceLogDirs.Do(createLogDirs) - if len(logDirs) == 0 { - return nil, "", errors.New("log: no log dirs") - } - name, link := logName(tag, t) - var lastErr error - for _, dir := range logDirs { - fname := filepath.Join(dir, name) - f, err := openOrCreate(fname, startup) - if err == nil { - symlink := filepath.Join(dir, link) - os.Remove(symlink) // ignore err - os.Symlink(name, symlink) // ignore err - return f, fname, nil - } - lastErr = err - } - return nil, "", fmt.Errorf("log: cannot create log: %v", lastErr) -} - -// The startup argument indicates whether this is the initial startup of klog. -// If startup is true, existing files are opened for appending instead of truncated. -func openOrCreate(name string, startup bool) (*os.File, error) { - if startup { - f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) - return f, err - } - f, err := os.Create(name) - return f, err -} diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_types.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_types.go index 25dd0f0ac..2e15d5454 100644 --- a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_types.go +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_types.go @@ -169,13 +169,10 @@ type SubscriptionsAPIFilter struct { // +optional Suffix map[string]string `json:"suffix,omitempty"` - // Extensions includes the list of additional filter dialects supported by - // specific broker implementations. Check out the documentation of the - // broker implementation you're using to know about what additional filters - // are supported. + // SQL is a CloudEvents SQL expression that will be evaluated to true or false against each CloudEvent. // // +optional - Extensions map[string]*runtime.RawExtension `json:",inline"` + SQL string `json:"sql,omitempty"` } // TriggerFilterAttributes is a map of context attribute names to values for diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_validation.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_validation.go index 772a33f17..ac033c1d8 100644 --- a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_validation.go +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_validation.go @@ -22,6 +22,7 @@ import ( "fmt" "regexp" + cesqlparser "github.com/cloudevents/sdk-go/sql/v2/parser" corev1 "k8s.io/api/core/v1" "knative.dev/pkg/apis" "knative.dev/pkg/kmp" @@ -193,6 +194,16 @@ func ValidateSubscriptionAPIFiltersList(ctx context.Context, filters []Subscript return errs } +func ValidateCESQLExpression(ctx context.Context, expression string) (errs *apis.FieldError) { + if expression == "" { + return nil + } + if _, err := cesqlparser.Parse(expression); err != nil { + return apis.ErrInvalidValue(expression, apis.CurrentField, err.Error()) + } + return nil +} + func ValidateSubscriptionAPIFilter(ctx context.Context, filter *SubscriptionsAPIFilter) (errs *apis.FieldError) { if filter == nil { return nil @@ -211,6 +222,8 @@ func ValidateSubscriptionAPIFilter(ctx context.Context, filter *SubscriptionsAPI ValidateSubscriptionAPIFiltersList(ctx, filter.Any).ViaField("any"), ).Also( ValidateSubscriptionAPIFilter(ctx, filter.Not).ViaField("not"), + ).Also( + ValidateCESQLExpression(ctx, filter.SQL).ViaField("sql"), ) return errs } @@ -262,7 +275,7 @@ func hasMultipleDialects(filter *SubscriptionsAPIFilter) bool { dialectFound = true } } - if len(filter.Extensions) > 0 && dialectFound { + if filter.SQL != "" && dialectFound { return true } return false diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/zz_generated.deepcopy.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/zz_generated.deepcopy.go index df8525537..e176c766b 100644 --- a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/zz_generated.deepcopy.go +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/zz_generated.deepcopy.go @@ -177,21 +177,6 @@ func (in *SubscriptionsAPIFilter) DeepCopyInto(out *SubscriptionsAPIFilter) { (*out)[key] = val } } - if in.Extensions != nil { - in, out := &in.Extensions, &out.Extensions - *out = make(map[string]*runtime.RawExtension, len(*in)) - for key, val := range *in { - var outVal *runtime.RawExtension - if val == nil { - (*out)[key] = nil - } else { - in, out := &val, &outVal - *out = new(runtime.RawExtension) - (*in).DeepCopyInto(*out) - } - (*out)[key] = outVal - } - } return } diff --git a/vendor/knative.dev/eventing/pkg/apis/sources/config/ping_defaults.go b/vendor/knative.dev/eventing/pkg/apis/sources/config/ping_defaults.go index e3a1fff15..ebe8f99ab 100644 --- a/vendor/knative.dev/eventing/pkg/apis/sources/config/ping_defaults.go +++ b/vendor/knative.dev/eventing/pkg/apis/sources/config/ping_defaults.go @@ -17,10 +17,9 @@ limitations under the License. package config import ( - "fmt" - "strconv" - corev1 "k8s.io/api/core/v1" + + cm "knative.dev/pkg/configmap" ) const ( @@ -28,7 +27,11 @@ const ( // configs that pings should use. PingDefaultsConfigName = "config-ping-defaults" - DataMaxSizeKey = "dataMaxSize" + DataMaxSizeKey = "data-max-size" + + // Legacy configuration item should be removed when a migration + // update script is released. + LegacyDataMaxSizeKey = "dataMaxSize" DefaultDataMaxSize = -1 ) @@ -37,16 +40,15 @@ const ( func NewPingDefaultsConfigFromMap(data map[string]string) (*PingDefaults, error) { nc := &PingDefaults{DataMaxSize: DefaultDataMaxSize} - // Parse out the MaxSizeKey - value, present := data[DataMaxSizeKey] - if !present || value == "" { - return nc, nil + if err := cm.Parse(data, + // Legacy for backwards compatibility + cm.AsInt64(LegacyDataMaxSizeKey, &nc.DataMaxSize), + + cm.AsInt64(DataMaxSizeKey, &nc.DataMaxSize), + ); err != nil { + return nil, err } - int64Value, err := strconv.ParseInt(value, 0, 64) - if err != nil { - return nil, fmt.Errorf("Failed to parse the entry: %s", err) - } - nc.DataMaxSize = int64Value + return nc, nil } @@ -57,7 +59,7 @@ func NewPingDefaultsConfigFromConfigMap(config *corev1.ConfigMap) (*PingDefaults // PingDefaults includes the default values to be populated by the webhook. type PingDefaults struct { - DataMaxSize int64 `json:"dataMaxSize"` + DataMaxSize int64 `json:"data-max-size"` } func (d *PingDefaults) GetPingConfig() *PingDefaults { diff --git a/vendor/knative.dev/pkg/apis/duck/v1/source_types.go b/vendor/knative.dev/pkg/apis/duck/v1/source_types.go index 5c5c030a1..bed832f32 100644 --- a/vendor/knative.dev/pkg/apis/duck/v1/source_types.go +++ b/vendor/knative.dev/pkg/apis/duck/v1/source_types.go @@ -180,13 +180,17 @@ func (s *Source) Validate(ctx context.Context) *apis.FieldError { } func (s *SourceSpec) Validate(ctx context.Context) *apis.FieldError { - if s.CloudEventOverrides == nil { - return nil + if s == nil { + return apis.ErrMissingField("spec") } - return s.CloudEventOverrides.Validate(ctx).ViaField("ceOverrides") + return s.Sink.Validate(ctx).ViaField("sink"). + Also(s.CloudEventOverrides.Validate(ctx).ViaField("ceOverrides")) } func (ceOverrides *CloudEventOverrides) Validate(ctx context.Context) *apis.FieldError { + if ceOverrides == nil { + return nil + } for key := range ceOverrides.Extensions { if err := validateExtensionName(key); err != nil { return err.ViaField("extensions") diff --git a/vendor/knative.dev/pkg/injection/config.go b/vendor/knative.dev/pkg/injection/config.go index f54f84b45..c3531b9e4 100644 --- a/vendor/knative.dev/pkg/injection/config.go +++ b/vendor/knative.dev/pkg/injection/config.go @@ -21,7 +21,7 @@ import ( "log" "k8s.io/client-go/rest" - "k8s.io/klog" + "k8s.io/klog/v2" "knative.dev/pkg/environment" ) diff --git a/vendor/knative.dev/pkg/leaderelection/config.go b/vendor/knative.dev/pkg/leaderelection/config.go index 0694395bf..f07c30cea 100644 --- a/vendor/knative.dev/pkg/leaderelection/config.go +++ b/vendor/knative.dev/pkg/leaderelection/config.go @@ -98,9 +98,9 @@ func (c *Config) GetComponentConfig(name string) ComponentConfig { func defaultConfig() *Config { return &Config{ Buckets: 1, - LeaseDuration: 15 * time.Second, - RenewDeadline: 10 * time.Second, - RetryPeriod: 2 * time.Second, + LeaseDuration: 60 * time.Second, + RenewDeadline: 40 * time.Second, + RetryPeriod: 10 * time.Second, } } diff --git a/vendor/knative.dev/pkg/leaderelection/doc.go b/vendor/knative.dev/pkg/leaderelection/doc.go new file mode 100644 index 000000000..fb7e162f7 --- /dev/null +++ b/vendor/knative.dev/pkg/leaderelection/doc.go @@ -0,0 +1,27 @@ +/* +Copyright 2020 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// LeaderElection provides an interface for controllers implementing using +// controller injection: +// https://github.com/knative/pkg/blob/main/injection/README.md +// +// Leaderelection uses the context-stuffing mechanism to provide config-driven +// management of multiple election strategies (currently, using Kubernetes +// etcd-based election primitives or StatefulSet indexes and counts). +// +// For more details, see the original design document: +// https://docs.google.com/document/d/e/2PACX-1vTh40N-Kk6EPNzYpITiLg8YJk0qZyZv7KgMpcQS72T9Lv_F2PQeGybx4TtH0E1N1aUgLQer7b8u3lDc/pub +package leaderelection diff --git a/vendor/knative.dev/serving/pkg/apis/config/features.go b/vendor/knative.dev/serving/pkg/apis/config/features.go index db4f212d6..0998025e3 100644 --- a/vendor/knative.dev/serving/pkg/apis/config/features.go +++ b/vendor/knative.dev/serving/pkg/apis/config/features.go @@ -54,6 +54,8 @@ func defaultFeaturesConfig() *Features { ContainerSpecAddCapabilities: Disabled, PodSpecTolerations: Disabled, PodSpecVolumesEmptyDir: Disabled, + PodSpecPersistentVolumeClaim: Disabled, + PodSpecPersistentVolumeWrite: Disabled, PodSpecInitContainers: Disabled, TagHeaderBasedRouting: Disabled, AutoDetectHTTP2: Disabled, @@ -79,6 +81,8 @@ func NewFeaturesConfigFromMap(data map[string]string) (*Features, error) { asFlag("kubernetes.podspec-tolerations", &nc.PodSpecTolerations), asFlag("kubernetes.podspec-volumes-emptydir", &nc.PodSpecVolumesEmptyDir), asFlag("kubernetes.podspec-init-containers", &nc.PodSpecInitContainers), + asFlag("kubernetes.podspec-persistent-volume-claim", &nc.PodSpecPersistentVolumeClaim), + asFlag("kubernetes.podspec-persistent-volume-write", &nc.PodSpecPersistentVolumeWrite), asFlag("tag-header-based-routing", &nc.TagHeaderBasedRouting), asFlag("autodetect-http2", &nc.AutoDetectHTTP2)); err != nil { return nil, err @@ -107,6 +111,8 @@ type Features struct { PodSpecTolerations Flag PodSpecVolumesEmptyDir Flag PodSpecInitContainers Flag + PodSpecPersistentVolumeClaim Flag + PodSpecPersistentVolumeWrite Flag TagHeaderBasedRouting Flag AutoDetectHTTP2 Flag } diff --git a/vendor/knative.dev/serving/pkg/apis/serving/fieldmask.go b/vendor/knative.dev/serving/pkg/apis/serving/fieldmask.go index 4ea939b29..32723a1f8 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/fieldmask.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/fieldmask.go @@ -45,6 +45,10 @@ func VolumeMask(ctx context.Context, in *corev1.Volume) *corev1.Volume { out.EmptyDir = in.EmptyDir } + if cfg.Features.PodSpecPersistentVolumeClaim != config.Disabled { + out.PersistentVolumeClaim = in.PersistentVolumeClaim + } + return out } @@ -67,6 +71,10 @@ func VolumeSourceMask(ctx context.Context, in *corev1.VolumeSource) *corev1.Volu out.EmptyDir = in.EmptyDir } + if cfg.Features.PodSpecPersistentVolumeClaim != config.Disabled { + out.PersistentVolumeClaim = in.PersistentVolumeClaim + } + // Too many disallowed fields to list return out diff --git a/vendor/knative.dev/serving/pkg/apis/serving/k8s_validation.go b/vendor/knative.dev/serving/pkg/apis/serving/k8s_validation.go index 608afa78a..eeed43fc8 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/k8s_validation.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/k8s_validation.go @@ -85,12 +85,7 @@ var ( func ValidateVolumes(ctx context.Context, vs []corev1.Volume, mountedVolumes sets.String) (map[string]corev1.Volume, *apis.FieldError) { volumes := make(map[string]corev1.Volume, len(vs)) var errs *apis.FieldError - features := config.FromContextOrDefaults(ctx).Features for i, volume := range vs { - if volume.EmptyDir != nil && features.PodSpecVolumesEmptyDir != config.Enabled { - errs = errs.Also((&apis.FieldError{Message: fmt.Sprintf("EmptyDir volume support is off, "+ - "but found EmptyDir volume %s", volume.Name)}).ViaIndex(i)) - } if _, ok := volumes[volume.Name]; ok { errs = errs.Also((&apis.FieldError{ Message: fmt.Sprintf("duplicate volume name %q", volume.Name), @@ -109,14 +104,36 @@ func ValidateVolumes(ctx context.Context, vs []corev1.Volume, mountedVolumes set return volumes, errs } +func validatePersistentVolumeClaims(volume corev1.VolumeSource, features *config.Features) *apis.FieldError { + var errs *apis.FieldError + if volume.PersistentVolumeClaim == nil { + return nil + } + if features.PodSpecPersistentVolumeClaim != config.Enabled { + errs = errs.Also(&apis.FieldError{Message: fmt.Sprintf("Persistent volume claim support is disabled, "+ + "but found persistent volume claim %s", volume.PersistentVolumeClaim.ClaimName)}) + } + isWriteEnabled := features.PodSpecPersistentVolumeWrite == config.Enabled + if !volume.PersistentVolumeClaim.ReadOnly && !isWriteEnabled { + errs = errs.Also(&apis.FieldError{Message: fmt.Sprintf("Persistent volume write support is disabled, "+ + "but found persistent volume claim %s that is not read-only", volume.PersistentVolumeClaim.ClaimName)}) + } + return errs +} + func validateVolume(ctx context.Context, volume corev1.Volume) *apis.FieldError { - errs := apis.CheckDisallowedFields(volume, *VolumeMask(ctx, &volume)) + features := config.FromContextOrDefaults(ctx).Features + errs := validatePersistentVolumeClaims(volume.VolumeSource, features) + if volume.EmptyDir != nil && features.PodSpecVolumesEmptyDir != config.Enabled { + errs = errs.Also(&apis.FieldError{Message: fmt.Sprintf("EmptyDir volume support is disabled, "+ + "but found EmptyDir volume %s", volume.Name)}) + } + errs = errs.Also(apis.CheckDisallowedFields(volume, *VolumeMask(ctx, &volume))) if volume.Name == "" { errs = apis.ErrMissingField("name") } else if len(validation.IsDNS1123Label(volume.Name)) != 0 { errs = apis.ErrInvalidValue(volume.Name, "name") } - vs := volume.VolumeSource errs = errs.Also(apis.CheckDisallowedFields(vs, *VolumeSourceMask(ctx, &vs))) var specified []string @@ -142,12 +159,20 @@ func validateVolume(ctx context.Context, volume corev1.Volume) *apis.FieldError specified = append(specified, "emptyDir") errs = errs.Also(validateEmptyDirFields(vs.EmptyDir).ViaField("emptyDir")) } + + if vs.PersistentVolumeClaim != nil { + specified = append(specified, "persistentVolumeClaim") + } + if len(specified) == 0 { fieldPaths := []string{"secret", "configMap", "projected"} cfg := config.FromContextOrDefaults(ctx) if cfg.Features.PodSpecVolumesEmptyDir == config.Enabled { fieldPaths = append(fieldPaths, "emptyDir") } + if cfg.Features.PodSpecPersistentVolumeClaim == config.Enabled { + fieldPaths = append(fieldPaths, "persistentVolumeClaim") + } errs = errs.Also(apis.ErrMissingOneOf(fieldPaths...)) } else if len(specified) > 1 { errs = errs.Also(apis.ErrMultipleOneOf(specified...)) @@ -319,7 +344,7 @@ func ValidatePodSpec(ctx context.Context, ps corev1.PodSpec) *apis.FieldError { volumes, err := ValidateVolumes(ctx, ps.Volumes, AllMountedVolumes(append(ps.InitContainers, ps.Containers...))) errs = errs.Also(err.ViaField("volumes")) - errs = errs.Also(validateInitContainers(ctx, ps.InitContainers, volumes)) + errs = errs.Also(validateInitContainers(ctx, ps.InitContainers, ps.Containers, volumes)) port, err := validateContainersPorts(ps.Containers) errs = errs.Also(err.ViaField("containers[*]")) @@ -341,7 +366,7 @@ func ValidatePodSpec(ctx context.Context, ps corev1.PodSpec) *apis.FieldError { return errs } -func validateInitContainers(ctx context.Context, containers []corev1.Container, volumes map[string]corev1.Volume) (errs *apis.FieldError) { +func validateInitContainers(ctx context.Context, containers, otherContainers []corev1.Container, volumes map[string]corev1.Volume) (errs *apis.FieldError) { if len(containers) == 0 { return nil } @@ -350,7 +375,17 @@ func validateInitContainers(ctx context.Context, containers []corev1.Container, return errs.Also(&apis.FieldError{Message: fmt.Sprintf("pod spec support for init-containers is off, "+ "but found %d init containers", len(containers))}) } + allNames := make(sets.String, len(otherContainers)+len(containers)) + for _, ctr := range otherContainers { + allNames.Insert(ctr.Name) + } for i := range containers { + if allNames.Has(containers[i].Name) { + errs = errs.Also(&apis.FieldError{ + Message: fmt.Sprintf("duplicate container name %q", containers[i].Name), + Paths: []string{"name"}, + }).ViaFieldIndex("containers", i) + } errs = errs.Also(validateInitContainer(ctx, containers[i], volumes).ViaFieldIndex("containers", i)) } return errs @@ -362,7 +397,16 @@ func validateContainers(ctx context.Context, containers []corev1.Container, volu return errs.Also(&apis.FieldError{Message: fmt.Sprintf("multi-container is off, "+ "but found %d containers", len(containers))}) } + allNames := make(sets.String, len(containers)) for i := range containers { + if allNames.Has(containers[i].Name) { + errs = errs.Also(&apis.FieldError{ + Message: fmt.Sprintf("duplicate container name %q", containers[i].Name), + Paths: []string{"name"}, + }).ViaFieldIndex("containers", i) + } else { + allNames.Insert(containers[i].Name) + } // Probes are not allowed on other than serving container, // ref: http://bit.ly/probes-condition if len(containers[i].Ports) == 0 { @@ -597,8 +641,21 @@ func validateVolumeMounts(mounts []corev1.VolumeMount, volumes map[string]corev1 } seenMountPath.Insert(filepath.Clean(vm.MountPath)) - if volumes[vm.Name].EmptyDir == nil && !vm.ReadOnly { - errs = errs.Also(apis.ErrMissingField("readOnly").ViaIndex(i)) + shouldCheckReadOnlyVolume := volumes[vm.Name].EmptyDir == nil && volumes[vm.Name].PersistentVolumeClaim == nil + if shouldCheckReadOnlyVolume && !vm.ReadOnly { + errs = errs.Also((&apis.FieldError{ + Message: "volume mount should be readOnly for this type of volume", + Paths: []string{"readOnly"}, + }).ViaIndex(i)) + } + + if volumes[vm.Name].PersistentVolumeClaim != nil { + if volumes[vm.Name].PersistentVolumeClaim.ReadOnly && !vm.ReadOnly { + errs = errs.Also((&apis.FieldError{ + Message: "volume is readOnly but volume mount is not", + Paths: []string{"readOnly"}, + }).ViaIndex(i)) + } } } return errs diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_defaults.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_defaults.go index 88724199f..354b12d89 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_defaults.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_defaults.go @@ -121,7 +121,7 @@ func (rs *RevisionSpec) applyDefault(ctx context.Context, container *corev1.Cont vNames := make(sets.String) for _, v := range rs.PodSpec.Volumes { - if v.EmptyDir != nil { + if v.EmptyDir != nil || v.PersistentVolumeClaim != nil { vNames.Insert(v.Name) } } diff --git a/vendor/modules.txt b/vendor/modules.txt index 306609d76..1dce83dbb 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,4 +1,4 @@ -# cloud.google.com/go/compute v1.3.0 +# cloud.google.com/go/compute v1.5.0 cloud.google.com/go/compute/metadata # contrib.go.opencensus.io/exporter/ocagent v0.7.1-0.20200907061046-05415f1de66d contrib.go.opencensus.io/exporter/ocagent @@ -31,7 +31,7 @@ github.com/BurntSushi/toml/internal # github.com/Masterminds/semver v1.5.0 ## explicit github.com/Masterminds/semver -# github.com/Microsoft/go-winio v0.5.1 +# github.com/Microsoft/go-winio v0.5.2 github.com/Microsoft/go-winio github.com/Microsoft/go-winio/pkg/guid github.com/Microsoft/go-winio/pkg/security @@ -86,7 +86,7 @@ github.com/acomagu/bufpipe # github.com/alecthomas/jsonschema v0.0.0-20210526225647-edb03dcab7bc ## explicit github.com/alecthomas/jsonschema -# github.com/antlr/antlr4 v0.0.0-20200503195918-621b933c7a7f +# github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220209173558-ad29539cd2e9 github.com/antlr/antlr4/runtime/Go/antlr # github.com/apex/log v1.9.0 github.com/apex/log @@ -151,7 +151,15 @@ github.com/census-instrumentation/opencensus-proto/gen-go/resource/v1 github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1 # github.com/cespare/xxhash/v2 v2.1.2 github.com/cespare/xxhash/v2 -# github.com/cloudevents/sdk-go/v2 v2.5.0 +# github.com/cloudevents/sdk-go/sql/v2 v2.8.0 +github.com/cloudevents/sdk-go/sql/v2 +github.com/cloudevents/sdk-go/sql/v2/expression +github.com/cloudevents/sdk-go/sql/v2/function +github.com/cloudevents/sdk-go/sql/v2/gen +github.com/cloudevents/sdk-go/sql/v2/parser +github.com/cloudevents/sdk-go/sql/v2/runtime +github.com/cloudevents/sdk-go/sql/v2/utils +# github.com/cloudevents/sdk-go/v2 v2.8.0 ## explicit github.com/cloudevents/sdk-go/v2 github.com/cloudevents/sdk-go/v2/binding @@ -167,15 +175,15 @@ github.com/cloudevents/sdk-go/v2/event/datacodec/xml github.com/cloudevents/sdk-go/v2/protocol github.com/cloudevents/sdk-go/v2/protocol/http github.com/cloudevents/sdk-go/v2/types -# github.com/containerd/cgroups v1.0.1 +# github.com/containerd/cgroups v1.0.3 github.com/containerd/cgroups/stats/v1 -# github.com/containerd/containerd v1.5.10 +# github.com/containerd/containerd v1.6.0 github.com/containerd/containerd/errdefs github.com/containerd/containerd/log github.com/containerd/containerd/pkg/userns github.com/containerd/containerd/platforms github.com/containerd/containerd/sys -# github.com/containerd/stargz-snapshotter/estargz v0.11.0 +# github.com/containerd/stargz-snapshotter/estargz v0.11.1 github.com/containerd/stargz-snapshotter/estargz github.com/containerd/stargz-snapshotter/estargz/errorutil # github.com/containers/image/v5 v5.19.1 @@ -401,8 +409,6 @@ github.com/go-logr/logr github.com/go-openapi/jsonpointer # github.com/go-openapi/jsonreference v0.19.6 github.com/go-openapi/jsonreference -# github.com/go-openapi/spec v0.20.4 -github.com/go-openapi/spec # github.com/go-openapi/swag v0.19.15 github.com/go-openapi/swag # github.com/gogo/protobuf v1.3.2 @@ -428,7 +434,7 @@ github.com/golang/protobuf/ptypes/timestamp github.com/golang/protobuf/ptypes/wrappers # github.com/google/btree v1.0.1 github.com/google/btree -# github.com/google/cel-go v0.7.3 +# github.com/google/cel-go v0.7.3 => github.com/google/cel-go v0.11.2 github.com/google/cel-go/cel github.com/google/cel-go/checker github.com/google/cel-go/checker/decls @@ -437,6 +443,7 @@ github.com/google/cel-go/common/containers github.com/google/cel-go/common/debug github.com/google/cel-go/common/operators github.com/google/cel-go/common/overloads +github.com/google/cel-go/common/runes github.com/google/cel-go/common/types github.com/google/cel-go/common/types/pb github.com/google/cel-go/common/types/ref @@ -453,7 +460,7 @@ github.com/google/go-cmp/cmp/internal/diff github.com/google/go-cmp/cmp/internal/flags github.com/google/go-cmp/cmp/internal/function github.com/google/go-cmp/cmp/internal/value -# github.com/google/go-containerregistry v0.8.1-0.20220219142810-1571d7fdc46e +# github.com/google/go-containerregistry v0.8.1-0.20220414143355-892d7a808387 ## explicit github.com/google/go-containerregistry/internal/and github.com/google/go-containerregistry/internal/estargz @@ -881,14 +888,14 @@ golang.org/x/text/transform golang.org/x/text/unicode/bidi golang.org/x/text/unicode/norm golang.org/x/text/width -# golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 +# golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 golang.org/x/time/rate # golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 golang.org/x/xerrors golang.org/x/xerrors/internal # gomodules.xyz/jsonpatch/v2 v2.2.0 gomodules.xyz/jsonpatch/v2 -# google.golang.org/api v0.67.0 +# google.golang.org/api v0.70.0 google.golang.org/api/support/bundler # google.golang.org/appengine v1.6.7 google.golang.org/appengine @@ -901,7 +908,7 @@ google.golang.org/appengine/internal/modules google.golang.org/appengine/internal/remote_api google.golang.org/appengine/internal/urlfetch google.golang.org/appengine/urlfetch -# google.golang.org/genproto v0.0.0-20220303160752-862486edd9cc +# google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6 google.golang.org/genproto/googleapis/api/expr/v1alpha1 google.golang.org/genproto/googleapis/api/httpbody google.golang.org/genproto/googleapis/rpc/status @@ -1059,7 +1066,7 @@ gotest.tools/v3/internal/assert gotest.tools/v3/internal/difflib gotest.tools/v3/internal/format gotest.tools/v3/internal/source -# k8s.io/api v0.23.4 => k8s.io/api v0.22.5 +# k8s.io/api v0.23.5 => k8s.io/api v0.22.5 ## explicit k8s.io/api/admissionregistration/v1 k8s.io/api/admissionregistration/v1beta1 @@ -1107,7 +1114,7 @@ k8s.io/api/storage/v1beta1 # k8s.io/apiextensions-apiserver v0.22.5 k8s.io/apiextensions-apiserver/pkg/apis/apiextensions k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1 -# k8s.io/apimachinery v0.23.4 => k8s.io/apimachinery v0.22.5 +# k8s.io/apimachinery v0.23.5 => k8s.io/apimachinery v0.22.5 ## explicit k8s.io/apimachinery/pkg/api/equality k8s.io/apimachinery/pkg/api/errors @@ -1164,7 +1171,7 @@ k8s.io/apimachinery/pkg/watch k8s.io/apimachinery/third_party/forked/golang/json k8s.io/apimachinery/third_party/forked/golang/netutil k8s.io/apimachinery/third_party/forked/golang/reflect -# k8s.io/cli-runtime v0.21.4 +# k8s.io/cli-runtime v0.22.5 k8s.io/cli-runtime/pkg/genericclioptions k8s.io/cli-runtime/pkg/printers k8s.io/cli-runtime/pkg/resource @@ -1300,8 +1307,6 @@ k8s.io/client-go/util/jsonpath k8s.io/client-go/util/keyutil k8s.io/client-go/util/retry k8s.io/client-go/util/workqueue -# k8s.io/klog v1.0.0 -k8s.io/klog # k8s.io/klog/v2 v2.40.1 k8s.io/klog/v2 # k8s.io/kube-openapi v0.0.0-20220124234850-424119656bbf @@ -1314,7 +1319,7 @@ k8s.io/utils/buffer k8s.io/utils/integer k8s.io/utils/pointer k8s.io/utils/trace -# knative.dev/client v0.28.0 +# knative.dev/client v0.29.0 ## explicit knative.dev/client/pkg/config knative.dev/client/pkg/errors @@ -1327,7 +1332,7 @@ knative.dev/client/pkg/serving/v1 knative.dev/client/pkg/util knative.dev/client/pkg/util/mock knative.dev/client/pkg/wait -# knative.dev/eventing v0.28.4 +# knative.dev/eventing v0.29.2-0.20220420140829-ce4fe0990d23 ## explicit knative.dev/eventing/pkg/apis/config knative.dev/eventing/pkg/apis/duck @@ -1351,9 +1356,10 @@ knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1 ## explicit knative.dev/hack # knative.dev/networking v0.0.0-20220120045035-ec849677a316 +## explicit knative.dev/networking/pkg/apis/networking knative.dev/networking/pkg/apis/networking/v1alpha1 -# knative.dev/pkg v0.0.0-20220222214539-0b8a9403de7e +# knative.dev/pkg v0.0.0-20220222214439-083dd97300e1 ## explicit knative.dev/pkg/apis knative.dev/pkg/apis/duck @@ -1385,7 +1391,7 @@ knative.dev/pkg/resolver knative.dev/pkg/signals knative.dev/pkg/system knative.dev/pkg/tracker -# knative.dev/serving v0.28.4 +# knative.dev/serving v0.29.5 ## explicit knative.dev/serving/pkg/apis/autoscaling knative.dev/serving/pkg/apis/autoscaling/v1alpha1 @@ -1399,13 +1405,13 @@ knative.dev/serving/pkg/autoscaler/config/autoscalerconfig knative.dev/serving/pkg/client/clientset/versioned/scheme knative.dev/serving/pkg/client/clientset/versioned/typed/serving/v1 knative.dev/serving/pkg/networking -# sigs.k8s.io/kustomize/api v0.8.8 +# sigs.k8s.io/kustomize/api v0.8.11 sigs.k8s.io/kustomize/api/builtins -sigs.k8s.io/kustomize/api/filesys sigs.k8s.io/kustomize/api/filters/annotations sigs.k8s.io/kustomize/api/filters/fieldspec sigs.k8s.io/kustomize/api/filters/filtersutil sigs.k8s.io/kustomize/api/filters/fsslice +sigs.k8s.io/kustomize/api/filters/iampolicygenerator sigs.k8s.io/kustomize/api/filters/imagetag sigs.k8s.io/kustomize/api/filters/labels sigs.k8s.io/kustomize/api/filters/nameref @@ -1414,6 +1420,7 @@ sigs.k8s.io/kustomize/api/filters/patchjson6902 sigs.k8s.io/kustomize/api/filters/patchstrategicmerge sigs.k8s.io/kustomize/api/filters/prefixsuffix sigs.k8s.io/kustomize/api/filters/refvar +sigs.k8s.io/kustomize/api/filters/replacement sigs.k8s.io/kustomize/api/filters/replicacount sigs.k8s.io/kustomize/api/filters/valueadd sigs.k8s.io/kustomize/api/hasher @@ -1439,19 +1446,20 @@ sigs.k8s.io/kustomize/api/kv sigs.k8s.io/kustomize/api/loader sigs.k8s.io/kustomize/api/provenance sigs.k8s.io/kustomize/api/provider -sigs.k8s.io/kustomize/api/resid sigs.k8s.io/kustomize/api/resmap sigs.k8s.io/kustomize/api/resource sigs.k8s.io/kustomize/api/types -# sigs.k8s.io/kustomize/kyaml v0.10.17 +# sigs.k8s.io/kustomize/kyaml v0.11.0 sigs.k8s.io/kustomize/kyaml/comments sigs.k8s.io/kustomize/kyaml/errors sigs.k8s.io/kustomize/kyaml/ext sigs.k8s.io/kustomize/kyaml/fieldmeta +sigs.k8s.io/kustomize/kyaml/filesys sigs.k8s.io/kustomize/kyaml/fn/runtime/container sigs.k8s.io/kustomize/kyaml/fn/runtime/exec sigs.k8s.io/kustomize/kyaml/fn/runtime/runtimeutil sigs.k8s.io/kustomize/kyaml/fn/runtime/starlark +sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/qri-io/starlib/util sigs.k8s.io/kustomize/kyaml/kio sigs.k8s.io/kustomize/kyaml/kio/filters @@ -1460,6 +1468,7 @@ sigs.k8s.io/kustomize/kyaml/openapi sigs.k8s.io/kustomize/kyaml/openapi/kubernetesapi sigs.k8s.io/kustomize/kyaml/openapi/kubernetesapi/v1204 sigs.k8s.io/kustomize/kyaml/openapi/kustomizationapi +sigs.k8s.io/kustomize/kyaml/resid sigs.k8s.io/kustomize/kyaml/runfn sigs.k8s.io/kustomize/kyaml/sets sigs.k8s.io/kustomize/kyaml/yaml @@ -1480,6 +1489,7 @@ sigs.k8s.io/structured-merge-diff/v4/typed sigs.k8s.io/structured-merge-diff/v4/value # sigs.k8s.io/yaml v1.3.0 sigs.k8s.io/yaml +# github.com/google/cel-go => github.com/google/cel-go v0.11.2 # github.com/openshift/source-to-image => github.com/boson-project/source-to-image v1.3.2 # k8s.io/api => k8s.io/api v0.22.5 # k8s.io/apimachinery => k8s.io/apimachinery v0.22.5 diff --git a/vendor/sigs.k8s.io/kustomize/api/builtins/AnnotationsTransformer.go b/vendor/sigs.k8s.io/kustomize/api/builtins/AnnotationsTransformer.go index 68d351e18..7064fa80c 100644 --- a/vendor/sigs.k8s.io/kustomize/api/builtins/AnnotationsTransformer.go +++ b/vendor/sigs.k8s.io/kustomize/api/builtins/AnnotationsTransformer.go @@ -27,16 +27,10 @@ func (p *AnnotationsTransformerPlugin) Transform(m resmap.ResMap) error { if len(p.Annotations) == 0 { return nil } - for _, r := range m.Resources() { - err := r.ApplyFilter(annotations.Filter{ - Annotations: p.Annotations, - FsSlice: p.FieldSpecs, - }) - if err != nil { - return err - } - } - return nil + return m.ApplyFilter(annotations.Filter{ + Annotations: p.Annotations, + FsSlice: p.FieldSpecs, + }) } func NewAnnotationsTransformerPlugin() resmap.TransformerPlugin { diff --git a/vendor/sigs.k8s.io/kustomize/api/builtins/HelmChartInflationGenerator.go b/vendor/sigs.k8s.io/kustomize/api/builtins/HelmChartInflationGenerator.go index 7037a01b5..2a654ad1f 100644 --- a/vendor/sigs.k8s.io/kustomize/api/builtins/HelmChartInflationGenerator.go +++ b/vendor/sigs.k8s.io/kustomize/api/builtins/HelmChartInflationGenerator.go @@ -267,6 +267,9 @@ func (p *HelmChartInflationGeneratorPlugin) templateCommand() []string { if p.ReleaseName != "" { args = append(args, p.ReleaseName) } + if p.Namespace != "" { + args = append(args, "--namespace", p.Namespace) + } args = append(args, filepath.Join(p.absChartHome(), p.Name)) if p.ValuesFile != "" { args = append(args, "--values", p.ValuesFile) @@ -277,6 +280,9 @@ func (p *HelmChartInflationGeneratorPlugin) templateCommand() []string { // I've tried placing the flag before and after the name argument. args = append(args, "--generate-name") } + if p.IncludeCRDs { + args = append(args, "--include-crds") + } return args } diff --git a/vendor/sigs.k8s.io/kustomize/api/builtins/IAMPolicyGenerator.go b/vendor/sigs.k8s.io/kustomize/api/builtins/IAMPolicyGenerator.go new file mode 100644 index 000000000..82a2dd603 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/api/builtins/IAMPolicyGenerator.go @@ -0,0 +1,33 @@ +// Code generated by pluginator on IAMPolicyGenerator; DO NOT EDIT. +// pluginator {unknown 1970-01-01T00:00:00Z } + +package builtins + +import ( + "sigs.k8s.io/kustomize/api/filters/iampolicygenerator" + "sigs.k8s.io/kustomize/api/resmap" + "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/yaml" +) + +type IAMPolicyGeneratorPlugin struct { + types.IAMPolicyGeneratorArgs +} + +func (p *IAMPolicyGeneratorPlugin) Config(h *resmap.PluginHelpers, config []byte) (err error) { + p.IAMPolicyGeneratorArgs = types.IAMPolicyGeneratorArgs{} + err = yaml.Unmarshal(config, p) + return +} + +func (p *IAMPolicyGeneratorPlugin) Generate() (resmap.ResMap, error) { + r := resmap.New() + err := r.ApplyFilter(iampolicygenerator.Filter{ + IAMPolicyGenerator: p.IAMPolicyGeneratorArgs, + }) + return r, err +} + +func NewIAMPolicyGeneratorPlugin() resmap.GeneratorPlugin { + return &IAMPolicyGeneratorPlugin{} +} diff --git a/vendor/sigs.k8s.io/kustomize/api/builtins/ImageTagTransformer.go b/vendor/sigs.k8s.io/kustomize/api/builtins/ImageTagTransformer.go index a09ef163d..52a44d385 100644 --- a/vendor/sigs.k8s.io/kustomize/api/builtins/ImageTagTransformer.go +++ b/vendor/sigs.k8s.io/kustomize/api/builtins/ImageTagTransformer.go @@ -25,24 +25,15 @@ func (p *ImageTagTransformerPlugin) Config( } func (p *ImageTagTransformerPlugin) Transform(m resmap.ResMap) error { - for _, r := range m.Resources() { - // traverse all fields at first - err := r.ApplyFilter(imagetag.LegacyFilter{ - ImageTag: p.ImageTag, - }) - if err != nil { - return err - } - // then use user specified field specs - err = r.ApplyFilter(imagetag.Filter{ - ImageTag: p.ImageTag, - FsSlice: p.FieldSpecs, - }) - if err != nil { - return err - } + if err := m.ApplyFilter(imagetag.LegacyFilter{ + ImageTag: p.ImageTag, + }); err != nil { + return err } - return nil + return m.ApplyFilter(imagetag.Filter{ + ImageTag: p.ImageTag, + FsSlice: p.FieldSpecs, + }) } func NewImageTagTransformerPlugin() resmap.TransformerPlugin { diff --git a/vendor/sigs.k8s.io/kustomize/api/builtins/LabelTransformer.go b/vendor/sigs.k8s.io/kustomize/api/builtins/LabelTransformer.go index 647e57efd..af601da5b 100644 --- a/vendor/sigs.k8s.io/kustomize/api/builtins/LabelTransformer.go +++ b/vendor/sigs.k8s.io/kustomize/api/builtins/LabelTransformer.go @@ -27,16 +27,10 @@ func (p *LabelTransformerPlugin) Transform(m resmap.ResMap) error { if len(p.Labels) == 0 { return nil } - for _, r := range m.Resources() { - err := r.ApplyFilter(labels.Filter{ - Labels: p.Labels, - FsSlice: p.FieldSpecs, - }) - if err != nil { - return err - } - } - return nil + return m.ApplyFilter(labels.Filter{ + Labels: p.Labels, + FsSlice: p.FieldSpecs, + }) } func NewLabelTransformerPlugin() resmap.TransformerPlugin { diff --git a/vendor/sigs.k8s.io/kustomize/api/builtins/NamespaceTransformer.go b/vendor/sigs.k8s.io/kustomize/api/builtins/NamespaceTransformer.go index 6794f26e8..39a514e8e 100644 --- a/vendor/sigs.k8s.io/kustomize/api/builtins/NamespaceTransformer.go +++ b/vendor/sigs.k8s.io/kustomize/api/builtins/NamespaceTransformer.go @@ -30,7 +30,7 @@ func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error { return nil } for _, r := range m.Resources() { - if r.IsEmpty() { + if r.IsNilOrEmpty() { // Don't mutate empty objects? continue } diff --git a/vendor/sigs.k8s.io/kustomize/api/builtins/PatchTransformer.go b/vendor/sigs.k8s.io/kustomize/api/builtins/PatchTransformer.go index 99f48e748..07038af1e 100644 --- a/vendor/sigs.k8s.io/kustomize/api/builtins/PatchTransformer.go +++ b/vendor/sigs.k8s.io/kustomize/api/builtins/PatchTransformer.go @@ -62,10 +62,10 @@ func (p *PatchTransformerPlugin) Config( if errSM == nil { p.loadedPatch = patchSM if p.Options["allowNameChange"] { - p.loadedPatch.SetAllowNameChange("true") + p.loadedPatch.AllowNameChange() } if p.Options["allowKindChange"] { - p.loadedPatch.SetAllowKindChange("true") + p.loadedPatch.AllowKindChange() } } else { p.decodedPatch = patchJson @@ -76,10 +76,9 @@ func (p *PatchTransformerPlugin) Config( func (p *PatchTransformerPlugin) Transform(m resmap.ResMap) error { if p.loadedPatch == nil { return p.transformJson6902(m, p.decodedPatch) - } else { - // The patch was a strategic merge patch - return p.transformStrategicMerge(m, p.loadedPatch) } + // The patch was a strategic merge patch + return p.transformStrategicMerge(m, p.loadedPatch) } // transformStrategicMerge applies the provided strategic merge patch diff --git a/vendor/sigs.k8s.io/kustomize/api/builtins/PrefixSuffixTransformer.go b/vendor/sigs.k8s.io/kustomize/api/builtins/PrefixSuffixTransformer.go index 20265d592..57a81a0fc 100644 --- a/vendor/sigs.k8s.io/kustomize/api/builtins/PrefixSuffixTransformer.go +++ b/vendor/sigs.k8s.io/kustomize/api/builtins/PrefixSuffixTransformer.go @@ -7,9 +7,9 @@ import ( "errors" "sigs.k8s.io/kustomize/api/filters/prefixsuffix" - "sigs.k8s.io/kustomize/api/resid" "sigs.k8s.io/kustomize/api/resmap" "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/kyaml/resid" "sigs.k8s.io/yaml" ) @@ -73,12 +73,11 @@ func (p *PrefixSuffixTransformerPlugin) Transform(m resmap.ResMap) error { r.StorePreviousId() } } - err := r.ApplyFilter(prefixsuffix.Filter{ + if err := r.ApplyFilter(prefixsuffix.Filter{ Prefix: p.Prefix, Suffix: p.Suffix, FieldSpec: fs, - }) - if err != nil { + }); err != nil { return err } } diff --git a/vendor/sigs.k8s.io/kustomize/api/builtins/ReplacementTransformer.go b/vendor/sigs.k8s.io/kustomize/api/builtins/ReplacementTransformer.go new file mode 100644 index 000000000..21e42c81e --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/api/builtins/ReplacementTransformer.go @@ -0,0 +1,59 @@ +// Code generated by pluginator on ReplacementTransformer; DO NOT EDIT. +// pluginator {unknown 1970-01-01T00:00:00Z } + +package builtins + +import ( + "fmt" + + "sigs.k8s.io/kustomize/api/filters/replacement" + "sigs.k8s.io/kustomize/api/resmap" + "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/yaml" +) + +// Replace values in targets with values from a source +type ReplacementTransformerPlugin struct { + ReplacementList []types.ReplacementField `json:"replacements,omitempty" yaml:"replacements,omitempty"` + Replacements []types.Replacement `json:"omitempty" yaml:"omitempty"` +} + +func (p *ReplacementTransformerPlugin) Config( + h *resmap.PluginHelpers, c []byte) (err error) { + p.ReplacementList = []types.ReplacementField{} + if err := yaml.Unmarshal(c, p); err != nil { + return err + } + + for _, r := range p.ReplacementList { + if r.Path != "" && (r.Source != nil || len(r.Targets) != 0) { + return fmt.Errorf("cannot specify both path and inline replacement") + } + if r.Path != "" { + // load the replacement from the path + content, err := h.Loader().Load(r.Path) + if err != nil { + return err + } + repl := types.Replacement{} + if err := yaml.Unmarshal(content, &repl); err != nil { + return err + } + p.Replacements = append(p.Replacements, repl) + } else { + // replacement information is already loaded + p.Replacements = append(p.Replacements, r.Replacement) + } + } + return nil +} + +func (p *ReplacementTransformerPlugin) Transform(m resmap.ResMap) (err error) { + return m.ApplyFilter(replacement.Filter{ + Replacements: p.Replacements, + }) +} + +func NewReplacementTransformerPlugin() resmap.TransformerPlugin { + return &ReplacementTransformerPlugin{} +} diff --git a/vendor/sigs.k8s.io/kustomize/api/builtins/ReplicaCountTransformer.go b/vendor/sigs.k8s.io/kustomize/api/builtins/ReplicaCountTransformer.go index 03fbf6f1e..120fab340 100644 --- a/vendor/sigs.k8s.io/kustomize/api/builtins/ReplicaCountTransformer.go +++ b/vendor/sigs.k8s.io/kustomize/api/builtins/ReplicaCountTransformer.go @@ -7,9 +7,9 @@ import ( "fmt" "sigs.k8s.io/kustomize/api/filters/replicacount" - "sigs.k8s.io/kustomize/api/resid" "sigs.k8s.io/kustomize/api/resmap" "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/kyaml/resid" "sigs.k8s.io/yaml" ) diff --git a/vendor/sigs.k8s.io/kustomize/api/filesys/filesystem.go b/vendor/sigs.k8s.io/kustomize/api/filesys/filesystem.go deleted file mode 100644 index 041b4bdb3..000000000 --- a/vendor/sigs.k8s.io/kustomize/api/filesys/filesystem.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2019 The Kubernetes Authors. -// SPDX-License-Identifier: Apache-2.0 - -// Package filesys provides a file system abstraction layer. -package filesys - -import ( - "path/filepath" -) - -const ( - Separator = string(filepath.Separator) - SelfDir = "." - ParentDir = ".." -) - -// FileSystem groups basic os filesystem methods. -// It's supposed be functional subset of https://golang.org/pkg/os -type FileSystem interface { - // Create a file. - Create(path string) (File, error) - // MkDir makes a directory. - Mkdir(path string) error - // MkDirAll makes a directory path, creating intervening directories. - MkdirAll(path string) error - // RemoveAll removes path and any children it contains. - RemoveAll(path string) error - // Open opens the named file for reading. - Open(path string) (File, error) - // IsDir returns true if the path is a directory. - IsDir(path string) bool - // CleanedAbs converts the given path into a - // directory and a file name, where the directory - // is represented as a ConfirmedDir and all that implies. - // If the entire path is a directory, the file component - // is an empty string. - CleanedAbs(path string) (ConfirmedDir, string, error) - // Exists is true if the path exists in the file system. - Exists(path string) bool - // Glob returns the list of matching files, - // emulating https://golang.org/pkg/path/filepath/#Glob - Glob(pattern string) ([]string, error) - // ReadFile returns the contents of the file at the given path. - ReadFile(path string) ([]byte, error) - // WriteFile writes the data to a file at the given path, - // overwriting anything that's already there. - WriteFile(path string, data []byte) error - // Walk walks the file system with the given WalkFunc. - Walk(path string, walkFn filepath.WalkFunc) error -} diff --git a/vendor/sigs.k8s.io/kustomize/api/filters/fieldspec/fieldspec.go b/vendor/sigs.k8s.io/kustomize/api/filters/fieldspec/fieldspec.go index d728e9ebc..8739d0733 100644 --- a/vendor/sigs.k8s.io/kustomize/api/filters/fieldspec/fieldspec.go +++ b/vendor/sigs.k8s.io/kustomize/api/filters/fieldspec/fieldspec.go @@ -11,6 +11,7 @@ import ( "sigs.k8s.io/kustomize/api/internal/utils" "sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/kustomize/kyaml/errors" + "sigs.k8s.io/kustomize/kyaml/resid" "sigs.k8s.io/kustomize/kyaml/yaml" ) @@ -45,12 +46,11 @@ type Filter struct { func (fltr Filter) Filter(obj *yaml.RNode) (*yaml.RNode, error) { // check if the FieldSpec applies to the object - if match, err := isMatchGVK(fltr.FieldSpec, obj); !match || err != nil { - return obj, errors.Wrap(err) + if match := isMatchGVK(fltr.FieldSpec, obj); !match { + return obj, nil } - fltr.path = utils.PathSplitter(fltr.FieldSpec.Path) - err := fltr.filter(obj) - if err != nil { + fltr.path = utils.PathSplitter(fltr.FieldSpec.Path, "/") + if err := fltr.filter(obj); err != nil { s, _ := obj.String() return nil, errors.WrapPrefixf(err, "considering field '%s' of object\n%v", fltr.FieldSpec.Path, s) @@ -158,28 +158,24 @@ func isSequenceField(name string) (string, bool) { } // isMatchGVK returns true if the fs.GVK matches the obj GVK. -func isMatchGVK(fs types.FieldSpec, obj *yaml.RNode) (bool, error) { - meta, err := obj.GetMeta() - if err != nil { - return false, err - } - if fs.Kind != "" && fs.Kind != meta.Kind { +func isMatchGVK(fs types.FieldSpec, obj *yaml.RNode) bool { + if kind := obj.GetKind(); fs.Kind != "" && fs.Kind != kind { // kind doesn't match - return false, err + return false } // parse the group and version from the apiVersion field - group, version := parseGV(meta.APIVersion) + group, version := resid.ParseGroupVersion(obj.GetApiVersion()) if fs.Group != "" && fs.Group != group { // group doesn't match - return false, nil + return false } if fs.Version != "" && fs.Version != version { // version doesn't match - return false, nil + return false } - return true, nil + return true } diff --git a/vendor/sigs.k8s.io/kustomize/api/filters/fieldspec/gvk.go b/vendor/sigs.k8s.io/kustomize/api/filters/fieldspec/gvk.go deleted file mode 100644 index 42e21a80d..000000000 --- a/vendor/sigs.k8s.io/kustomize/api/filters/fieldspec/gvk.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2019 The Kubernetes Authors. -// SPDX-License-Identifier: Apache-2.0 -package fieldspec - -import ( - "strings" - - "sigs.k8s.io/kustomize/api/resid" - "sigs.k8s.io/kustomize/kyaml/yaml" -) - -// Return true for 'v' followed by a 1 or 2, and don't look at rest. -// I.e. 'v1', 'v1beta1', 'v2', would return true. -func looksLikeACoreApiVersion(s string) bool { - if len(s) < 2 { - return false - } - if s[0:1] != "v" { - return false - } - return s[1:2] == "1" || s[1:2] == "2" -} - -// parseGV parses apiVersion field into group and version. -func parseGV(apiVersion string) (group, version string) { - // parse the group and version from the apiVersion field - parts := strings.SplitN(apiVersion, "/", 2) - group = parts[0] - if len(parts) > 1 { - version = parts[1] - } - // Special case the original "apiVersion" of what - // we now call the "core" (empty) group. - if version == "" && looksLikeACoreApiVersion(group) { - version = group - group = "" - } - return -} - -// GetGVK parses the metadata into a GVK -func GetGVK(meta yaml.ResourceMeta) resid.Gvk { - group, version := parseGV(meta.APIVersion) - return resid.Gvk{ - Group: group, - Version: version, - Kind: meta.Kind, - } -} diff --git a/vendor/sigs.k8s.io/kustomize/api/filters/iampolicygenerator/doc.go b/vendor/sigs.k8s.io/kustomize/api/filters/iampolicygenerator/doc.go new file mode 100644 index 000000000..d0ac6d91f --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/api/filters/iampolicygenerator/doc.go @@ -0,0 +1,3 @@ +// Package gkesagenerator contains a kio.Filter that that generates a +// iampolicy-related resources for a given cloud provider +package iampolicygenerator diff --git a/vendor/sigs.k8s.io/kustomize/api/filters/iampolicygenerator/iampolicygenerator.go b/vendor/sigs.k8s.io/kustomize/api/filters/iampolicygenerator/iampolicygenerator.go new file mode 100644 index 000000000..c1f8593fb --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/api/filters/iampolicygenerator/iampolicygenerator.go @@ -0,0 +1,55 @@ +// Copyright 2021 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package iampolicygenerator + +import ( + "fmt" + + "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/kyaml/yaml" +) + +type Filter struct { + IAMPolicyGenerator types.IAMPolicyGeneratorArgs `json:",inline,omitempty" yaml:",inline,omitempty"` +} + +// Filter adds a GKE service account object to nodes +func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) { + switch f.IAMPolicyGenerator.Cloud { + case types.GKE: + IAMPolicyResources, err := f.generateGkeIAMPolicyResources() + if err != nil { + return nil, err + } + nodes = append(nodes, IAMPolicyResources...) + default: + return nil, fmt.Errorf("cloud provider %s not supported yet", f.IAMPolicyGenerator.Cloud) + } + return nodes, nil +} + +func (f Filter) generateGkeIAMPolicyResources() ([]*yaml.RNode, error) { + var result []*yaml.RNode + input := fmt.Sprintf(` +apiVersion: v1 +kind: ServiceAccount +metadata: + annotations: + iam.gke.io/gcp-service-account: %s@%s.iam.gserviceaccount.com + name: %s +`, f.IAMPolicyGenerator.ServiceAccount.Name, + f.IAMPolicyGenerator.ProjectId, + f.IAMPolicyGenerator.KubernetesService.Name) + + if f.IAMPolicyGenerator.Namespace != "" { + input = input + fmt.Sprintf("\n namespace: %s", f.IAMPolicyGenerator.Namespace) + } + + sa, err := yaml.Parse(input) + if err != nil { + return nil, err + } + + return append(result, sa), nil +} diff --git a/vendor/sigs.k8s.io/kustomize/api/filters/imagetag/legacy.go b/vendor/sigs.k8s.io/kustomize/api/filters/imagetag/legacy.go index 5014e9c82..d07080b8e 100644 --- a/vendor/sigs.k8s.io/kustomize/api/filters/imagetag/legacy.go +++ b/vendor/sigs.k8s.io/kustomize/api/filters/imagetag/legacy.go @@ -4,6 +4,7 @@ package imagetag import ( + "sigs.k8s.io/kustomize/api/internal/utils" "sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/kustomize/kyaml/kio" "sigs.k8s.io/kustomize/kyaml/yaml" @@ -74,7 +75,7 @@ func (f findFieldsFilter) walk(node *yaml.RNode) error { return err } key := n.Key.YNode().Value - if contains(f.fields, key) { + if utils.StringSliceContains(f.fields, key) { return f.fieldCallback(n.Value) } return nil @@ -87,15 +88,6 @@ func (f findFieldsFilter) walk(node *yaml.RNode) error { return nil } -func contains(slice []string, str string) bool { - for _, s := range slice { - if s == str { - return true - } - } - return false -} - func checkImageTagsFn(imageTag types.Image) fieldCallback { return func(node *yaml.RNode) error { if node.YNode().Kind != yaml.SequenceNode { diff --git a/vendor/sigs.k8s.io/kustomize/api/filters/nameref/nameref.go b/vendor/sigs.k8s.io/kustomize/api/filters/nameref/nameref.go index a048d97f1..850059fb2 100644 --- a/vendor/sigs.k8s.io/kustomize/api/filters/nameref/nameref.go +++ b/vendor/sigs.k8s.io/kustomize/api/filters/nameref/nameref.go @@ -6,11 +6,11 @@ import ( "github.com/pkg/errors" "sigs.k8s.io/kustomize/api/filters/fieldspec" - "sigs.k8s.io/kustomize/api/resid" "sigs.k8s.io/kustomize/api/resmap" "sigs.k8s.io/kustomize/api/resource" "sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/kustomize/kyaml/kio" + "sigs.k8s.io/kustomize/kyaml/resid" "sigs.k8s.io/kustomize/kyaml/yaml" ) @@ -184,7 +184,7 @@ func (f Filter) recordTheReferral(referral *resource.Resource) { // getRoleRefGvk returns a Gvk in the roleRef field. Return error // if the roleRef, roleRef/apiGroup or roleRef/kind is missing. -func getRoleRefGvk(n *yaml.RNode) (*resid.Gvk, error) { +func getRoleRefGvk(n *resource.Resource) (*resid.Gvk, error) { roleRef, err := n.Pipe(yaml.Lookup("roleRef")) if err != nil { return nil, err @@ -257,8 +257,7 @@ func previousIdSelectedByGvk(gvk *resid.Gvk) sieveFunc { // If the we are updating a 'roleRef/name' field, the 'apiGroup' and 'kind' // fields in the same 'roleRef' map must be considered. -// If either object is cluster-scoped (!IsNamespaceableKind), there -// can be a referral. +// If either object is cluster-scoped, there can be a referral. // E.g. a RoleBinding (which exists in a namespace) can refer // to a ClusterRole (cluster-scoped) object. // https://kubernetes.io/docs/reference/access-authn-authz/rbac/#role-and-clusterrole @@ -270,7 +269,7 @@ func (f Filter) roleRefFilter() sieveFunc { if !strings.HasSuffix(f.NameFieldToUpdate.Path, "roleRef/name") { return acceptAll } - roleRefGvk, err := getRoleRefGvk(f.Referrer.AsRNode()) + roleRefGvk, err := getRoleRefGvk(f.Referrer) if err != nil { return acceptAll } @@ -285,12 +284,12 @@ func prefixSuffixEquals(other resource.ResCtx) sieveFunc { func (f Filter) sameCurrentNamespaceAsReferrer() sieveFunc { referrerCurId := f.Referrer.CurId() - if !referrerCurId.IsNamespaceableKind() { + if referrerCurId.IsClusterScoped() { // If the referrer is cluster-scoped, let anything through. return acceptAll } return func(r *resource.Resource) bool { - if !r.CurId().IsNamespaceableKind() { + if r.CurId().IsClusterScoped() { // Allow cluster-scoped through. return true } diff --git a/vendor/sigs.k8s.io/kustomize/api/filters/namespace/namespace.go b/vendor/sigs.k8s.io/kustomize/api/filters/namespace/namespace.go index 69458e198..e554600bc 100644 --- a/vendor/sigs.k8s.io/kustomize/api/filters/namespace/namespace.go +++ b/vendor/sigs.k8s.io/kustomize/api/filters/namespace/namespace.go @@ -4,11 +4,11 @@ package namespace import ( - "sigs.k8s.io/kustomize/api/filters/fieldspec" "sigs.k8s.io/kustomize/api/filters/filtersutil" "sigs.k8s.io/kustomize/api/filters/fsslice" "sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/kustomize/kyaml/kio" + "sigs.k8s.io/kustomize/kyaml/resid" "sigs.k8s.io/kustomize/kyaml/yaml" ) @@ -54,16 +54,11 @@ func (ns Filter) run(node *yaml.RNode) (*yaml.RNode, error) { // hacks applies the namespace transforms that are hardcoded rather // than specified through FieldSpecs. func (ns Filter) hacks(obj *yaml.RNode) error { - meta, err := obj.GetMeta() - if err != nil { + gvk := resid.GvkFromNode(obj) + if err := ns.metaNamespaceHack(obj, gvk); err != nil { return err } - - if err := ns.metaNamespaceHack(obj, meta); err != nil { - return err - } - - return ns.roleBindingHack(obj, meta) + return ns.roleBindingHack(obj, gvk) } // metaNamespaceHack is a hack for implementing the namespace transform @@ -74,9 +69,8 @@ func (ns Filter) hacks(obj *yaml.RNode) error { // This hack should be updated to allow individual resources to specify // if they are cluster scoped through either an annotation on the resources, // or through inlined OpenAPI on the resource as a YAML comment. -func (ns Filter) metaNamespaceHack(obj *yaml.RNode, meta yaml.ResourceMeta) error { - gvk := fieldspec.GetGVK(meta) - if !gvk.IsNamespaceableKind() { +func (ns Filter) metaNamespaceHack(obj *yaml.RNode, gvk resid.Gvk) error { + if gvk.IsClusterScoped() { return nil } f := fsslice.Filter{ @@ -104,8 +98,8 @@ func (ns Filter) metaNamespaceHack(obj *yaml.RNode, meta yaml.ResourceMeta) erro // ... // - name: "something-else" # this will not have the namespace set // ... -func (ns Filter) roleBindingHack(obj *yaml.RNode, meta yaml.ResourceMeta) error { - if meta.Kind != roleBindingKind && meta.Kind != clusterRoleBindingKind { +func (ns Filter) roleBindingHack(obj *yaml.RNode, gvk resid.Gvk) error { + if gvk.Kind != roleBindingKind && gvk.Kind != clusterRoleBindingKind { return nil } diff --git a/vendor/sigs.k8s.io/kustomize/api/filters/replacement/doc.go b/vendor/sigs.k8s.io/kustomize/api/filters/replacement/doc.go new file mode 100644 index 000000000..9d9357905 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/api/filters/replacement/doc.go @@ -0,0 +1,4 @@ +// Package replacement contains a kio.Filter implementation of the kustomize +// replacement transformer (accepts sources and looks for targets to replace +// their values with values from the sources). +package replacement diff --git a/vendor/sigs.k8s.io/kustomize/api/filters/replacement/replacement.go b/vendor/sigs.k8s.io/kustomize/api/filters/replacement/replacement.go new file mode 100644 index 000000000..7988c322b --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/api/filters/replacement/replacement.go @@ -0,0 +1,180 @@ +// Copyright 2021 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package replacement + +import ( + "fmt" + "strings" + + "sigs.k8s.io/kustomize/api/internal/utils" + "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/kyaml/resid" + "sigs.k8s.io/kustomize/kyaml/yaml" +) + +type Filter struct { + Replacements []types.Replacement `json:"replacements,omitempty" yaml:"replacements,omitempty"` +} + +// Filter replaces values of targets with values from sources +func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) { + for _, r := range f.Replacements { + if r.Source == nil || r.Targets == nil { + return nil, fmt.Errorf("replacements must specify a source and at least one target") + } + value, err := getReplacement(nodes, &r) + if err != nil { + return nil, err + } + nodes, err = applyReplacement(nodes, value, r.Targets) + if err != nil { + return nil, err + } + } + return nodes, nil +} + +func applyReplacement(nodes []*yaml.RNode, value *yaml.RNode, targets []*types.TargetSelector) ([]*yaml.RNode, error) { + for _, t := range targets { + if t.Select == nil { + return nil, fmt.Errorf("target must specify resources to select") + } + if len(t.FieldPaths) == 0 { + t.FieldPaths = []string{types.DefaultReplacementFieldPath} + } + for _, n := range nodes { + ids, err := utils.MakeResIds(n) + if err != nil { + return nil, err + } + for _, id := range ids { + if id.IsSelectedBy(t.Select.ResId) && !rejectId(t.Reject, &id) { + err := applyToNode(n, value, t) + if err != nil { + return nil, err + } + break + } + } + } + } + return nodes, nil +} + +func rejectId(rejects []*types.Selector, id *resid.ResId) bool { + for _, r := range rejects { + if id.IsSelectedBy(r.ResId) { + return true + } + } + return false +} + +func applyToNode(node *yaml.RNode, value *yaml.RNode, target *types.TargetSelector) error { + for _, fp := range target.FieldPaths { + fieldPath := utils.SmarterPathSplitter(fp, ".") + var t *yaml.RNode + var err error + if target.Options != nil && target.Options.Create { + t, err = node.Pipe(yaml.LookupCreate(value.YNode().Kind, fieldPath...)) + } else { + t, err = node.Pipe(yaml.Lookup(fieldPath...)) + } + if err != nil { + return err + } + if t != nil { + if err = setTargetValue(target.Options, t, value); err != nil { + return err + } + } + } + return nil +} + +func setTargetValue(options *types.FieldOptions, t *yaml.RNode, value *yaml.RNode) error { + value = value.Copy() + if options != nil && options.Delimiter != "" { + if t.YNode().Kind != yaml.ScalarNode { + return fmt.Errorf("delimiter option can only be used with scalar nodes") + } + tv := strings.Split(t.YNode().Value, options.Delimiter) + v := yaml.GetValue(value) + // TODO: Add a way to remove an element + switch { + case options.Index < 0: // prefix + tv = append([]string{v}, tv...) + case options.Index >= len(tv): // suffix + tv = append(tv, v) + default: // replace an element + tv[options.Index] = v + } + value.YNode().Value = strings.Join(tv, options.Delimiter) + } + t.SetYNode(value.YNode()) + return nil +} + +func getReplacement(nodes []*yaml.RNode, r *types.Replacement) (*yaml.RNode, error) { + source, err := selectSourceNode(nodes, r.Source) + if err != nil { + return nil, err + } + + if r.Source.FieldPath == "" { + r.Source.FieldPath = types.DefaultReplacementFieldPath + } + fieldPath := utils.SmarterPathSplitter(r.Source.FieldPath, ".") + + rn, err := source.Pipe(yaml.Lookup(fieldPath...)) + if err != nil { + return nil, err + } + if !rn.IsNilOrEmpty() { + return getRefinedValue(r.Source.Options, rn) + } + return rn, nil +} + +func getRefinedValue(options *types.FieldOptions, rn *yaml.RNode) (*yaml.RNode, error) { + if options == nil || options.Delimiter == "" { + return rn, nil + } + if rn.YNode().Kind != yaml.ScalarNode { + return nil, fmt.Errorf("delimiter option can only be used with scalar nodes") + } + value := strings.Split(yaml.GetValue(rn), options.Delimiter) + if options.Index >= len(value) || options.Index < 0 { + return nil, fmt.Errorf("options.index %d is out of bounds for value %s", options.Index, yaml.GetValue(rn)) + } + n := rn.Copy() + n.YNode().Value = value[options.Index] + return n, nil +} + +// selectSourceNode finds the node that matches the selector, returning +// an error if multiple or none are found +func selectSourceNode(nodes []*yaml.RNode, selector *types.SourceSelector) (*yaml.RNode, error) { + var matches []*yaml.RNode + for _, n := range nodes { + ids, err := utils.MakeResIds(n) + if err != nil { + return nil, err + } + for _, id := range ids { + if id.IsSelectedBy(selector.ResId) { + if len(matches) > 0 { + return nil, fmt.Errorf( + "multiple matches for selector %s", selector) + } + matches = append(matches, n) + break + } + } + } + if len(matches) == 0 { + return nil, fmt.Errorf("nothing selected by %s", selector) + } + return matches[0], nil +} diff --git a/vendor/sigs.k8s.io/kustomize/api/filters/valueadd/valueadd.go b/vendor/sigs.k8s.io/kustomize/api/filters/valueadd/valueadd.go index 326466a45..f8e6b2f82 100644 --- a/vendor/sigs.k8s.io/kustomize/api/filters/valueadd/valueadd.go +++ b/vendor/sigs.k8s.io/kustomize/api/filters/valueadd/valueadd.go @@ -6,7 +6,7 @@ package valueadd import ( "strings" - "sigs.k8s.io/kustomize/api/filesys" + "sigs.k8s.io/kustomize/kyaml/filesys" "sigs.k8s.io/kustomize/kyaml/kio" "sigs.k8s.io/kustomize/kyaml/yaml" ) diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/accumulator/loadconfigfromcrds.go b/vendor/sigs.k8s.io/kustomize/api/internal/accumulator/loadconfigfromcrds.go index d48c7a9dc..cac47c0de 100644 --- a/vendor/sigs.k8s.io/kustomize/api/internal/accumulator/loadconfigfromcrds.go +++ b/vendor/sigs.k8s.io/kustomize/api/internal/accumulator/loadconfigfromcrds.go @@ -7,13 +7,13 @@ import ( "encoding/json" "strings" - "github.com/go-openapi/spec" "github.com/pkg/errors" - "sigs.k8s.io/kustomize/api/filesys" + "k8s.io/kube-openapi/pkg/validation/spec" "sigs.k8s.io/kustomize/api/ifc" "sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig" - "sigs.k8s.io/kustomize/api/resid" "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/kyaml/filesys" + "sigs.k8s.io/kustomize/kyaml/resid" "sigs.k8s.io/yaml" ) @@ -178,9 +178,12 @@ func loadCrdIntoConfig( } } if property.Ref.GetURL() != nil { - loadCrdIntoConfig( + err = loadCrdIntoConfig( theConfig, theGvk, theMap, property.Ref.String(), append(path, propName)) + if err != nil { + return + } } } return nil diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/accumulator/resaccumulator.go b/vendor/sigs.k8s.io/kustomize/api/internal/accumulator/resaccumulator.go index b49db9b12..2723feafc 100644 --- a/vendor/sigs.k8s.io/kustomize/api/internal/accumulator/resaccumulator.go +++ b/vendor/sigs.k8s.io/kustomize/api/internal/accumulator/resaccumulator.go @@ -9,9 +9,9 @@ import ( "strings" "sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig" - "sigs.k8s.io/kustomize/api/resid" "sigs.k8s.io/kustomize/api/resmap" "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/kyaml/resid" ) // ResAccumulator accumulates resources and the rules @@ -72,7 +72,7 @@ func (ra *ResAccumulator) MergeVars(incoming []types.Var) error { for _, v := range incoming { targetId := resid.NewResIdWithNamespace(v.ObjRef.GVK(), v.ObjRef.Name, v.ObjRef.Namespace) idMatcher := targetId.GvknEquals - if targetId.Namespace != "" || !targetId.IsNamespaceableKind() { + if targetId.Namespace != "" || targetId.IsClusterScoped() { // Preserve backward compatibility. An empty namespace means // wildcard search on the namespace hence we still use GvknEquals idMatcher = targetId.Equals @@ -107,6 +107,7 @@ func (ra *ResAccumulator) findVarValueFromResources(v types.Var) (interface{}, e for _, res := range ra.resMap.Resources() { for _, varName := range res.GetRefVarNames() { if varName == v.Name { + //nolint: staticcheck s, err := res.GetFieldValue(v.FieldRef.FieldPath) if err != nil { return "", fmt.Errorf( diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/generators/configmap.go b/vendor/sigs.k8s.io/kustomize/api/internal/generators/configmap.go index 19a0e2832..47498aaa5 100644 --- a/vendor/sigs.k8s.io/kustomize/api/internal/generators/configmap.go +++ b/vendor/sigs.k8s.io/kustomize/api/internal/generators/configmap.go @@ -40,6 +40,13 @@ func MakeConfigMap( if err = rn.LoadMapIntoConfigMapData(m); err != nil { return nil, err } - copyLabelsAndAnnotations(rn, args.Options) + err = copyLabelsAndAnnotations(rn, args.Options) + if err != nil { + return nil, err + } + err = setImmutable(rn, args.Options) + if err != nil { + return nil, err + } return rn, nil } diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/generators/secret.go b/vendor/sigs.k8s.io/kustomize/api/internal/generators/secret.go index a46f497db..9afaff156 100644 --- a/vendor/sigs.k8s.io/kustomize/api/internal/generators/secret.go +++ b/vendor/sigs.k8s.io/kustomize/api/internal/generators/secret.go @@ -54,5 +54,6 @@ func MakeSecret( return nil, err } copyLabelsAndAnnotations(rn, args.Options) + setImmutable(rn, args.Options) return rn, nil } diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/generators/utils.go b/vendor/sigs.k8s.io/kustomize/api/internal/generators/utils.go index d1630fc84..82040d420 100644 --- a/vendor/sigs.k8s.io/kustomize/api/internal/generators/utils.go +++ b/vendor/sigs.k8s.io/kustomize/api/internal/generators/utils.go @@ -76,3 +76,16 @@ func copyLabelsAndAnnotations( } return nil } + +func setImmutable( + rn *yaml.RNode, opts *types.GeneratorOptions) error { + if opts == nil { + return nil + } + if opts.Immutable { + if _, err := rn.Pipe(yaml.SetField("immutable", yaml.NewScalarRNode("true"))); err != nil { + return err + } + } + return nil +} diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/git/cloner.go b/vendor/sigs.k8s.io/kustomize/api/internal/git/cloner.go index e3daccd88..78f4f32cb 100644 --- a/vendor/sigs.k8s.io/kustomize/api/internal/git/cloner.go +++ b/vendor/sigs.k8s.io/kustomize/api/internal/git/cloner.go @@ -4,7 +4,7 @@ package git import ( - "sigs.k8s.io/kustomize/api/filesys" + "sigs.k8s.io/kustomize/kyaml/filesys" ) // Cloner is a function that can clone a git repo. @@ -14,7 +14,7 @@ type Cloner func(repoSpec *RepoSpec) error // to say, some remote API, to obtain a local clone of // a remote repo. func ClonerUsingGitExec(repoSpec *RepoSpec) error { - r, err := newCmdRunner() + r, err := newCmdRunner(repoSpec.Timeout) if err != nil { return err } @@ -36,7 +36,10 @@ func ClonerUsingGitExec(repoSpec *RepoSpec) error { if err = r.run("checkout", "FETCH_HEAD"); err != nil { return err } - return r.run("submodule", "update", "--init", "--recursive") + if repoSpec.Submodules { + return r.run("submodule", "update", "--init", "--recursive") + } + return nil } // DoNothingCloner returns a cloner that only sets diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/git/gitrunner.go b/vendor/sigs.k8s.io/kustomize/api/internal/git/gitrunner.go index 94bb78c60..fcc7130cd 100644 --- a/vendor/sigs.k8s.io/kustomize/api/internal/git/gitrunner.go +++ b/vendor/sigs.k8s.io/kustomize/api/internal/git/gitrunner.go @@ -8,13 +8,10 @@ import ( "time" "github.com/pkg/errors" - "sigs.k8s.io/kustomize/api/filesys" "sigs.k8s.io/kustomize/api/internal/utils" + "sigs.k8s.io/kustomize/kyaml/filesys" ) -// Arbitrary, but non-infinite, timeout for running commands. -const defaultDuration = 27 * time.Second - // gitRunner runs the external git binary. type gitRunner struct { gitProgram string @@ -24,7 +21,7 @@ type gitRunner struct { // newCmdRunner returns a gitRunner if it can find the binary. // It also creats a temp directory for cloning repos. -func newCmdRunner() (*gitRunner, error) { +func newCmdRunner(timeout time.Duration) (*gitRunner, error) { gitProgram, err := exec.LookPath("git") if err != nil { return nil, errors.Wrap(err, "no 'git' program on path") @@ -35,7 +32,7 @@ func newCmdRunner() (*gitRunner, error) { } return &gitRunner{ gitProgram: gitProgram, - duration: defaultDuration, + duration: timeout, dir: dir, }, nil } diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/git/repospec.go b/vendor/sigs.k8s.io/kustomize/api/internal/git/repospec.go index ad8dfc24d..5a935f510 100644 --- a/vendor/sigs.k8s.io/kustomize/api/internal/git/repospec.go +++ b/vendor/sigs.k8s.io/kustomize/api/internal/git/repospec.go @@ -5,11 +5,13 @@ package git import ( "fmt" + "net/url" "path/filepath" - "regexp" + "strconv" "strings" + "time" - "sigs.k8s.io/kustomize/api/filesys" + "sigs.k8s.io/kustomize/kyaml/filesys" ) // Used as a temporary non-empty occupant of the cloneDir @@ -44,6 +46,12 @@ type RepoSpec struct { // e.g. .git or empty in case of _git is present GitSuffix string + + // Submodules indicates whether or not to clone git submodules. + Submodules bool + + // Timeout is the maximum duration allowed for execing git commands. + Timeout time.Duration } // CloneSpec returns a string suitable for "git clone {spec}". @@ -70,6 +78,7 @@ func (x *RepoSpec) Cleaner(fSys filesys.FileSystem) func() error { return func() error { return fSys.RemoveAll(x.Dir.String()) } } +// NewRepoSpecFromUrl parses git-like urls. // From strings like git@github.com:someOrg/someRepo.git or // https://github.com/someOrg/someRepo?ref=someHash, extract // the parts. @@ -77,7 +86,7 @@ func NewRepoSpecFromUrl(n string) (*RepoSpec, error) { if filepath.IsAbs(n) { return nil, fmt.Errorf("uri looks like abs path: %s", n) } - host, orgRepo, path, gitRef, gitSuffix := parseGitUrl(n) + host, orgRepo, path, gitRef, gitSubmodules, suffix, gitTimeout := parseGitUrl(n) if orgRepo == "" { return nil, fmt.Errorf("url lacks orgRepo: %s", n) } @@ -86,28 +95,28 @@ func NewRepoSpecFromUrl(n string) (*RepoSpec, error) { } return &RepoSpec{ raw: n, Host: host, OrgRepo: orgRepo, - Dir: notCloned, Path: path, Ref: gitRef, GitSuffix: gitSuffix}, nil + Dir: notCloned, Path: path, Ref: gitRef, GitSuffix: suffix, + Submodules: gitSubmodules, Timeout: gitTimeout}, nil } const ( - refQuery = "?ref=" - refQueryRegex = "\\?(version|ref)=" - gitSuffix = ".git" - gitDelimiter = "_git/" + refQuery = "?ref=" + gitSuffix = ".git" + gitDelimiter = "_git/" ) // From strings like git@github.com:someOrg/someRepo.git or // https://github.com/someOrg/someRepo?ref=someHash, extract // the parts. func parseGitUrl(n string) ( - host string, orgRepo string, path string, gitRef string, gitSuff string) { + host string, orgRepo string, path string, gitRef string, gitSubmodules bool, gitSuff string, gitTimeout time.Duration) { if strings.Contains(n, gitDelimiter) { index := strings.Index(n, gitDelimiter) // Adding _git/ to host host = normalizeGitHostSpec(n[:index+len(gitDelimiter)]) orgRepo = strings.Split(strings.Split(n[index+len(gitDelimiter):], "/")[0], "?")[0] - path, gitRef = peelQuery(n[index+len(gitDelimiter)+len(orgRepo):]) + path, gitRef, gitTimeout, gitSubmodules = peelQuery(n[index+len(gitDelimiter)+len(orgRepo):]) return } host, n = parseHostSpec(n) @@ -116,35 +125,75 @@ func parseGitUrl(n string) ( index := strings.Index(n, gitSuffix) orgRepo = n[0:index] n = n[index+len(gitSuffix):] - path, gitRef = peelQuery(n) + if n[0] == '/' { + n = n[1:] + } + path, gitRef, gitTimeout, gitSubmodules = peelQuery(n) return } i := strings.Index(n, "/") if i < 1 { - return "", "", "", "", "" + path, gitRef, gitTimeout, gitSubmodules = peelQuery(n) + return } j := strings.Index(n[i+1:], "/") if j >= 0 { j += i + 1 orgRepo = n[:j] - path, gitRef = peelQuery(n[j+1:]) + path, gitRef, gitTimeout, gitSubmodules = peelQuery(n[j+1:]) return } path = "" - orgRepo, gitRef = peelQuery(n) - return host, orgRepo, path, gitRef, gitSuff + orgRepo, gitRef, gitTimeout, gitSubmodules = peelQuery(n) + return host, orgRepo, path, gitRef, gitSubmodules, gitSuff, gitTimeout } -func peelQuery(arg string) (string, string) { +// Clone git submodules by default. +const defaultSubmodules = true - r, _ := regexp.Compile(refQueryRegex) - j := r.FindStringIndex(arg) +// Arbitrary, but non-infinite, timeout for running commands. +const defaultTimeout = 27 * time.Second - if len(j) > 0 { - return arg[:j[0]], arg[j[0]+len(r.FindString(arg)):] +func peelQuery(arg string) (string, string, time.Duration, bool) { + // Parse the given arg into a URL. In the event of a parse failure, return + // our defaults. + parsed, err := url.Parse(arg) + if err != nil { + return arg, "", defaultTimeout, defaultSubmodules } - return arg, "" + values := parsed.Query() + + // ref is the desired git ref to target. Can be specified by in a git URL + // with ?ref= or ?version=, although ref takes precedence. + ref := values.Get("version") + if queryValue := values.Get("ref"); queryValue != "" { + ref = queryValue + } + + // depth is the desired git exec timeout. Can be specified by in a git URL + // with ?timeout=. + duration := defaultTimeout + if queryValue := values.Get("timeout"); queryValue != "" { + // Attempt to first parse as a number of integer seconds (like "61"), + // and then attempt to parse as a suffixed duration (like "61s"). + if intValue, err := strconv.Atoi(queryValue); err == nil && intValue > 0 { + duration = time.Duration(intValue) * time.Second + } else if durationValue, err := time.ParseDuration(queryValue); err == nil && durationValue > 0 { + duration = durationValue + } + } + + // submodules indicates if git submodule cloning is desired. Can be + // specified by in a git URL with ?submodules=. + submodules := defaultSubmodules + if queryValue := values.Get("submodules"); queryValue != "" { + if boolValue, err := strconv.ParseBool(queryValue); err == nil { + submodules = boolValue + } + } + + return parsed.Path, ref, duration, submodules } func parseHostSpec(n string) (string, string) { diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig/namebackreferences.go b/vendor/sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig/namebackreferences.go index e458786c4..354f70e51 100644 --- a/vendor/sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig/namebackreferences.go +++ b/vendor/sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig/namebackreferences.go @@ -6,8 +6,8 @@ package builtinconfig import ( "strings" - "sigs.k8s.io/kustomize/api/resid" "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/kyaml/resid" ) // NameBackReferences is an association between a gvk.GVK (a ReferralTarget) diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers/builtinplugintype_string.go b/vendor/sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers/builtinplugintype_string.go index 7b775fadb..e87fe90e4 100644 --- a/vendor/sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers/builtinplugintype_string.go +++ b/vendor/sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers/builtinplugintype_string.go @@ -11,24 +11,26 @@ func _() { _ = x[Unknown-0] _ = x[AnnotationsTransformer-1] _ = x[ConfigMapGenerator-2] - _ = x[HashTransformer-3] - _ = x[ImageTagTransformer-4] - _ = x[LabelTransformer-5] - _ = x[LegacyOrderTransformer-6] - _ = x[NamespaceTransformer-7] - _ = x[PatchJson6902Transformer-8] - _ = x[PatchStrategicMergeTransformer-9] - _ = x[PatchTransformer-10] - _ = x[PrefixSuffixTransformer-11] - _ = x[ReplicaCountTransformer-12] - _ = x[SecretGenerator-13] - _ = x[ValueAddTransformer-14] - _ = x[HelmChartInflationGenerator-15] + _ = x[IAMPolicyGenerator-3] + _ = x[HashTransformer-4] + _ = x[ImageTagTransformer-5] + _ = x[LabelTransformer-6] + _ = x[LegacyOrderTransformer-7] + _ = x[NamespaceTransformer-8] + _ = x[PatchJson6902Transformer-9] + _ = x[PatchStrategicMergeTransformer-10] + _ = x[PatchTransformer-11] + _ = x[PrefixSuffixTransformer-12] + _ = x[ReplicaCountTransformer-13] + _ = x[SecretGenerator-14] + _ = x[ValueAddTransformer-15] + _ = x[HelmChartInflationGenerator-16] + _ = x[ReplacementTransformer-17] } -const _BuiltinPluginType_name = "UnknownAnnotationsTransformerConfigMapGeneratorHashTransformerImageTagTransformerLabelTransformerLegacyOrderTransformerNamespaceTransformerPatchJson6902TransformerPatchStrategicMergeTransformerPatchTransformerPrefixSuffixTransformerReplicaCountTransformerSecretGeneratorValueAddTransformerHelmChartInflationGenerator" +const _BuiltinPluginType_name = "UnknownAnnotationsTransformerConfigMapGeneratorIAMPolicyGeneratorHashTransformerImageTagTransformerLabelTransformerLegacyOrderTransformerNamespaceTransformerPatchJson6902TransformerPatchStrategicMergeTransformerPatchTransformerPrefixSuffixTransformerReplicaCountTransformerSecretGeneratorValueAddTransformerHelmChartInflationGeneratorReplacementTransformer" -var _BuiltinPluginType_index = [...]uint16{0, 7, 29, 47, 62, 81, 97, 119, 139, 163, 193, 209, 232, 255, 270, 289, 316} +var _BuiltinPluginType_index = [...]uint16{0, 7, 29, 47, 65, 80, 99, 115, 137, 157, 181, 211, 227, 250, 273, 288, 307, 334, 356} func (i BuiltinPluginType) String() string { if i < 0 || i >= BuiltinPluginType(len(_BuiltinPluginType_index)-1) { diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers/builtins.go b/vendor/sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers/builtins.go index f53583981..7d5e8fce1 100644 --- a/vendor/sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers/builtins.go +++ b/vendor/sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers/builtins.go @@ -15,6 +15,7 @@ const ( Unknown BuiltinPluginType = iota AnnotationsTransformer ConfigMapGenerator + IAMPolicyGenerator HashTransformer ImageTagTransformer LabelTransformer @@ -28,6 +29,7 @@ const ( SecretGenerator ValueAddTransformer HelmChartInflationGenerator + ReplacementTransformer ) var stringToBuiltinPluginTypeMap map[string]BuiltinPluginType @@ -57,6 +59,7 @@ func GetBuiltinPluginType(n string) BuiltinPluginType { var GeneratorFactories = map[BuiltinPluginType]func() resmap.GeneratorPlugin{ ConfigMapGenerator: builtins.NewConfigMapGeneratorPlugin, + IAMPolicyGenerator: builtins.NewIAMPolicyGeneratorPlugin, SecretGenerator: builtins.NewSecretGeneratorPlugin, HelmChartInflationGenerator: builtins.NewHelmChartInflationGeneratorPlugin, } @@ -72,6 +75,7 @@ var TransformerFactories = map[BuiltinPluginType]func() resmap.TransformerPlugin PatchStrategicMergeTransformer: builtins.NewPatchStrategicMergeTransformerPlugin, PatchTransformer: builtins.NewPatchTransformerPlugin, PrefixSuffixTransformer: builtins.NewPrefixSuffixTransformerPlugin, + ReplacementTransformer: builtins.NewReplacementTransformerPlugin, ReplicaCountTransformer: builtins.NewReplicaCountTransformerPlugin, ValueAddTransformer: builtins.NewValueAddTransformerPlugin, } diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/plugins/execplugin/execplugin.go b/vendor/sigs.k8s.io/kustomize/api/internal/plugins/execplugin/execplugin.go index a6f801ebb..9380558cb 100644 --- a/vendor/sigs.k8s.io/kustomize/api/internal/plugins/execplugin/execplugin.go +++ b/vendor/sigs.k8s.io/kustomize/api/internal/plugins/execplugin/execplugin.go @@ -89,7 +89,10 @@ type argsConfig struct { func (p *ExecPlugin) processOptionalArgsFields() error { var c argsConfig - yaml.Unmarshal(p.cfg, &c) + err := yaml.Unmarshal(p.cfg, &c) + if err != nil { + return err + } if c.ArgsOneLiner != "" { p.args, _ = shlex.Split(c.ArgsOneLiner) } diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/plugins/fnplugin/fnplugin.go b/vendor/sigs.k8s.io/kustomize/api/internal/plugins/fnplugin/fnplugin.go index ddd980d74..76be4b076 100644 --- a/vendor/sigs.k8s.io/kustomize/api/internal/plugins/fnplugin/fnplugin.go +++ b/vendor/sigs.k8s.io/kustomize/api/internal/plugins/fnplugin/fnplugin.go @@ -78,6 +78,7 @@ func NewFnPlugin(o *types.FnPluginLoadingOptions) *FnPlugin { EnableExec: o.EnableExec, StorageMounts: toStorageMounts(o.Mounts), Env: o.Env, + AsCurrentUser: o.AsCurrentUser, }, } } diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/plugins/loader/loader.go b/vendor/sigs.k8s.io/kustomize/api/internal/plugins/loader/loader.go index 0cbdfbe21..7bcce4315 100644 --- a/vendor/sigs.k8s.io/kustomize/api/internal/plugins/loader/loader.go +++ b/vendor/sigs.k8s.io/kustomize/api/internal/plugins/loader/loader.go @@ -13,17 +13,17 @@ import ( "strings" "github.com/pkg/errors" - "sigs.k8s.io/kustomize/api/filesys" "sigs.k8s.io/kustomize/api/ifc" "sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers" "sigs.k8s.io/kustomize/api/internal/plugins/execplugin" "sigs.k8s.io/kustomize/api/internal/plugins/fnplugin" "sigs.k8s.io/kustomize/api/internal/plugins/utils" "sigs.k8s.io/kustomize/api/konfig" - "sigs.k8s.io/kustomize/api/resid" "sigs.k8s.io/kustomize/api/resmap" "sigs.k8s.io/kustomize/api/resource" "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/kyaml/filesys" + "sigs.k8s.io/kustomize/kyaml/resid" ) // Loader loads plugins using a file loader (a different loader). diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/plugins/utils/utils.go b/vendor/sigs.k8s.io/kustomize/api/internal/plugins/utils/utils.go index 7fa461191..d1c2af766 100644 --- a/vendor/sigs.k8s.io/kustomize/api/internal/plugins/utils/utils.go +++ b/vendor/sigs.k8s.io/kustomize/api/internal/plugins/utils/utils.go @@ -12,11 +12,11 @@ import ( "strconv" "time" - "sigs.k8s.io/kustomize/api/filesys" "sigs.k8s.io/kustomize/api/konfig" "sigs.k8s.io/kustomize/api/resmap" "sigs.k8s.io/kustomize/api/resource" "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/kyaml/filesys" "sigs.k8s.io/yaml" ) @@ -137,7 +137,9 @@ func GetResMapWithIDAnnotation(rm resmap.ResMap) (resmap.ResMap, error) { } annotations := r.GetAnnotations() annotations[idAnnotation] = string(idString) - r.SetAnnotations(annotations) + if err = r.SetAnnotations(annotations); err != nil { + return nil, err + } } return inputRM, nil } @@ -158,7 +160,10 @@ func UpdateResMapValues(pluginName string, h *resmap.PluginHelpers, output []byt } for _, r := range resources { - removeIDAnnotation(r) // stale--not manipulated by plugin transformers + // stale--not manipulated by plugin transformers + if err = removeIDAnnotation(r); err != nil { + return err + } // Add to the new map, checking for duplicates if err := newMap.Append(r); err != nil { @@ -175,7 +180,7 @@ func UpdateResMapValues(pluginName string, h *resmap.PluginHelpers, output []byt return err } if oldIdx != -1 { - rm.GetByIndex(oldIdx).ResetPrimaryData(r) + rm.GetByIndex(oldIdx).ResetRNode(r) } else { if err := rm.Append(r); err != nil { return err @@ -187,21 +192,20 @@ func UpdateResMapValues(pluginName string, h *resmap.PluginHelpers, output []byt for _, id := range rm.AllIds() { newIdx, _ := newMap.GetIndexOfCurrentId(id) if newIdx == -1 { - rm.Remove(id) + if err = rm.Remove(id); err != nil { + return err + } } } return nil } -func removeIDAnnotation(r *resource.Resource) { +func removeIDAnnotation(r *resource.Resource) error { // remove the annotation set by Kustomize to track the resource annotations := r.GetAnnotations() delete(annotations, idAnnotation) - if len(annotations) == 0 { - annotations = nil - } - r.SetAnnotations(annotations) + return r.SetAnnotations(annotations) } // UpdateResourceOptions updates the generator options for each resource in the @@ -224,10 +228,9 @@ func UpdateResourceOptions(rm resmap.ResMap) (resmap.ResMap, error) { } delete(annotations, HashAnnotation) delete(annotations, BehaviorAnnotation) - if len(annotations) == 0 { - annotations = nil + if err := r.SetAnnotations(annotations); err != nil { + return nil, err } - r.SetAnnotations(annotations) r.SetOptions(types.NewGenArgs( &types.GeneratorArgs{ Behavior: behavior, diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/target/kusttarget.go b/vendor/sigs.k8s.io/kustomize/api/internal/target/kusttarget.go index efbb71ea6..43d3637dd 100644 --- a/vendor/sigs.k8s.io/kustomize/api/internal/target/kusttarget.go +++ b/vendor/sigs.k8s.io/kustomize/api/internal/target/kusttarget.go @@ -303,16 +303,18 @@ func (kt *KustTarget) runValidators(ra *accumulator.ResAccumulator) error { if err != nil { return err } - new := ra.ResMap().DeepCopy() - kt.removeValidatedByLabel(new) - if err = orignal.ErrorIfNotEqualSets(new); err != nil { + newMap := ra.ResMap().DeepCopy() + if err = kt.removeValidatedByLabel(newMap); err != nil { + return err + } + if err = orignal.ErrorIfNotEqualSets(newMap); err != nil { return fmt.Errorf("validator shouldn't modify the resource map: %v", err) } } return nil } -func (kt *KustTarget) removeValidatedByLabel(rm resmap.ResMap) { +func (kt *KustTarget) removeValidatedByLabel(rm resmap.ResMap) error { resources := rm.Resources() for _, r := range resources { labels := r.GetLabels() @@ -320,12 +322,11 @@ func (kt *KustTarget) removeValidatedByLabel(rm resmap.ResMap) { continue } delete(labels, konfig.ValidatedByLabelKey) - if len(labels) == 0 { - r.SetLabels(nil) - } else { - r.SetLabels(labels) + if err := r.SetLabels(labels); err != nil { + return err } } + return nil } // accumulateResources fills the given resourceAccumulator diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/target/kusttarget_configplugin.go b/vendor/sigs.k8s.io/kustomize/api/internal/target/kusttarget_configplugin.go index 2715af471..7bb15516e 100644 --- a/vendor/sigs.k8s.io/kustomize/api/internal/target/kusttarget_configplugin.go +++ b/vendor/sigs.k8s.io/kustomize/api/internal/target/kusttarget_configplugin.go @@ -57,6 +57,7 @@ func (kt *KustTarget) configureBuiltinTransformers( builtinhelpers.PatchJson6902Transformer, builtinhelpers.ReplicaCountTransformer, builtinhelpers.ImageTagTransformer, + builtinhelpers.ReplacementTransformer, } { r, err := transformerConfigurators[bpt]( kt, bpt, builtinhelpers.TransformerFactories[bpt], tc) @@ -323,6 +324,21 @@ var transformerConfigurators = map[builtinhelpers.BuiltinPluginType]func( } return }, + builtinhelpers.ReplacementTransformer: func( + kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, _ *builtinconfig.TransformerConfig) ( + result []resmap.Transformer, err error) { + var c struct { + Replacements []types.ReplacementField + } + c.Replacements = kt.kustomization.Replacements + p := f() + err = kt.configureBuiltinPlugin(p, c, bpt) + if err != nil { + return nil, err + } + result = append(result, p) + return result, nil + }, builtinhelpers.ReplicaCountTransformer: func( kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, tc *builtinconfig.TransformerConfig) ( result []resmap.Transformer, err error) { diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/utils/makeResIds.go b/vendor/sigs.k8s.io/kustomize/api/internal/utils/makeResIds.go new file mode 100644 index 000000000..3f6b17a3f --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/api/internal/utils/makeResIds.go @@ -0,0 +1,79 @@ +package utils + +import ( + "fmt" + "strings" + + "sigs.k8s.io/kustomize/api/konfig" + "sigs.k8s.io/kustomize/kyaml/resid" + "sigs.k8s.io/kustomize/kyaml/yaml" +) + +const ( + BuildAnnotationPreviousKinds = konfig.ConfigAnnoDomain + "/previousKinds" + BuildAnnotationPreviousNames = konfig.ConfigAnnoDomain + "/previousNames" + BuildAnnotationPrefixes = konfig.ConfigAnnoDomain + "/prefixes" + BuildAnnotationSuffixes = konfig.ConfigAnnoDomain + "/suffixes" + BuildAnnotationPreviousNamespaces = konfig.ConfigAnnoDomain + "/previousNamespaces" + + // the following are only for patches, to specify whether they can change names + // and kinds of their targets + BuildAnnotationAllowNameChange = konfig.ConfigAnnoDomain + "/allowNameChange" + BuildAnnotationAllowKindChange = konfig.ConfigAnnoDomain + "/allowKindChange" + Allowed = "allowed" +) + +// MakeResIds returns all of an RNode's current and previous Ids +func MakeResIds(n *yaml.RNode) ([]resid.ResId, error) { + var result []resid.ResId + apiVersion := n.Field(yaml.APIVersionField) + var group, version string + if apiVersion != nil { + group, version = resid.ParseGroupVersion(yaml.GetValue(apiVersion.Value)) + } + result = append(result, resid.NewResIdWithNamespace( + resid.Gvk{Group: group, Version: version, Kind: n.GetKind()}, n.GetName(), n.GetNamespace()), + ) + prevIds, err := PrevIds(n) + if err != nil { + return nil, err + } + result = append(result, prevIds...) + return result, nil +} + +// PrevIds returns all of an RNode's previous Ids +func PrevIds(n *yaml.RNode) ([]resid.ResId, error) { + var ids []resid.ResId + // TODO: merge previous names and namespaces into one list of + // pairs on one annotation so there is no chance of error + annotations := n.GetAnnotations() + if _, ok := annotations[BuildAnnotationPreviousNames]; !ok { + return nil, nil + } + names := strings.Split(annotations[BuildAnnotationPreviousNames], ",") + ns := strings.Split(annotations[BuildAnnotationPreviousNamespaces], ",") + kinds := strings.Split(annotations[BuildAnnotationPreviousKinds], ",") + // This should never happen + if len(names) != len(ns) || len(names) != len(kinds) { + return nil, fmt.Errorf( + "number of previous names, " + + "number of previous namespaces, " + + "number of previous kinds not equal") + } + for i := range names { + meta, err := n.GetMeta() + if err != nil { + return nil, err + } + group, version := resid.ParseGroupVersion(meta.APIVersion) + gvk := resid.Gvk{ + Group: group, + Version: version, + Kind: kinds[i], + } + ids = append(ids, resid.NewResIdWithNamespace( + gvk, names[i], ns[i])) + } + return ids, nil +} diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/utils/pathsplitter.go b/vendor/sigs.k8s.io/kustomize/api/internal/utils/pathsplitter.go index c8d2f3342..aa560299f 100644 --- a/vendor/sigs.k8s.io/kustomize/api/internal/utils/pathsplitter.go +++ b/vendor/sigs.k8s.io/kustomize/api/internal/utils/pathsplitter.go @@ -5,18 +5,60 @@ package utils import "strings" -// PathSplitter splits a slash delimited string, permitting escaped slashes. -func PathSplitter(path string) []string { - ps := strings.Split(path, "/") +// TODO: Move these to kyaml + +// PathSplitter splits a delimited string, permitting escaped delimiters. +func PathSplitter(path string, delimiter string) []string { + ps := strings.Split(path, delimiter) var res []string res = append(res, ps[0]) for i := 1; i < len(ps); i++ { last := len(res) - 1 if strings.HasSuffix(res[last], `\`) { - res[last] = strings.TrimSuffix(res[last], `\`) + "/" + ps[i] + res[last] = strings.TrimSuffix(res[last], `\`) + delimiter + ps[i] } else { res = append(res, ps[i]) } } return res } + +// SmarterPathSplitter splits a path, retaining bracketed elements. +// If the element is a list entry identifier (defined by the '='), +// it will retain the brackets. +// E.g. "[name=com.foo.someapp]" survives as one thing after splitting +// "spec.template.spec.containers.[name=com.foo.someapp].image" +// See kyaml/yaml/match.go for use of list entry identifiers. +// If the element is a mapping entry identifier, it will remove the +// brackets. +// E.g. "a.b.c" survives as one thing after splitting +// "metadata.annotations.[a.b.c] +// This function uses `PathSplitter`, so it also respects escaped delimiters. +func SmarterPathSplitter(path string, delimiter string) []string { + var result []string + split := PathSplitter(path, delimiter) + + for i := 0; i < len(split); i++ { + elem := split[i] + if strings.HasPrefix(elem, "[") && !strings.HasSuffix(elem, "]") { + // continue until we find the matching "]" + bracketed := []string{elem} + for i < len(split)-1 { + i++ + bracketed = append(bracketed, split[i]) + if strings.HasSuffix(split[i], "]") { + break + } + } + bracketedStr := strings.Join(bracketed, delimiter) + if strings.Contains(bracketedStr, "=") { + result = append(result, bracketedStr) + } else { + result = append(result, strings.Trim(bracketedStr, "[]")) + } + } else { + result = append(result, elem) + } + } + return result +} diff --git a/vendor/sigs.k8s.io/kustomize/api/internal/utils/stringslice.go b/vendor/sigs.k8s.io/kustomize/api/internal/utils/stringslice.go new file mode 100644 index 000000000..3dc422725 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/api/internal/utils/stringslice.go @@ -0,0 +1,44 @@ +// Copyright 2020 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package utils + +// StringSliceIndex returns the index of the str, else -1. +func StringSliceIndex(slice []string, str string) int { + for i := range slice { + if slice[i] == str { + return i + } + } + return -1 +} + +// StringSliceContains returns true if the slice has the string. +func StringSliceContains(slice []string, str string) bool { + for _, s := range slice { + if s == str { + return true + } + } + return false +} + +// SameEndingSubSlice returns true if the slices end the same way, e.g. +// {"a", "b", "c"}, {"b", "c"} => true +// {"a", "b", "c"}, {"a", "b"} => false +// If one slice is empty and the other is not, return false. +func SameEndingSubSlice(shortest, longest []string) bool { + if len(shortest) > len(longest) { + longest, shortest = shortest, longest + } + diff := len(longest) - len(shortest) + if len(shortest) == 0 { + return diff == 0 + } + for i := len(shortest) - 1; i >= 0; i-- { + if longest[i+diff] != shortest[i] { + return false + } + } + return true +} diff --git a/vendor/sigs.k8s.io/kustomize/api/konfig/builtinpluginconsts/namereference.go b/vendor/sigs.k8s.io/kustomize/api/konfig/builtinpluginconsts/namereference.go index a9af15706..26a344f4d 100644 --- a/vendor/sigs.k8s.io/kustomize/api/konfig/builtinpluginconsts/namereference.go +++ b/vendor/sigs.k8s.io/kustomize/api/konfig/builtinpluginconsts/namereference.go @@ -3,9 +3,6 @@ package builtinpluginconsts -// TODO: rename 'fieldSpecs' to 'referrers' for clarity. -// This will, however, break anyone using a custom config. - const ( nameReferenceFieldSpecs = ` nameReference: diff --git a/vendor/sigs.k8s.io/kustomize/api/konfig/doc.go b/vendor/sigs.k8s.io/kustomize/api/konfig/doc.go index 44f659afb..8c5f8f2cd 100644 --- a/vendor/sigs.k8s.io/kustomize/api/konfig/doc.go +++ b/vendor/sigs.k8s.io/kustomize/api/konfig/doc.go @@ -2,5 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 // Package konfig provides configuration methods and constants -// for the kustomize API. +// for the kustomize API, e.g. the set of file names to look for +// to identify a kustomization root. package konfig diff --git a/vendor/sigs.k8s.io/kustomize/api/konfig/plugins.go b/vendor/sigs.k8s.io/kustomize/api/konfig/plugins.go index 0615f1768..30bd3b6e3 100644 --- a/vendor/sigs.k8s.io/kustomize/api/konfig/plugins.go +++ b/vendor/sigs.k8s.io/kustomize/api/konfig/plugins.go @@ -8,8 +8,8 @@ import ( "path/filepath" "runtime" - "sigs.k8s.io/kustomize/api/filesys" "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/kyaml/filesys" ) const ( diff --git a/vendor/sigs.k8s.io/kustomize/api/krusty/kustomizer.go b/vendor/sigs.k8s.io/kustomize/api/krusty/kustomizer.go index 08af7ee75..b06a8221c 100644 --- a/vendor/sigs.k8s.io/kustomize/api/krusty/kustomizer.go +++ b/vendor/sigs.k8s.io/kustomize/api/krusty/kustomizer.go @@ -8,7 +8,6 @@ import ( "path/filepath" "sigs.k8s.io/kustomize/api/builtins" - "sigs.k8s.io/kustomize/api/filesys" pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader" "sigs.k8s.io/kustomize/api/internal/target" "sigs.k8s.io/kustomize/api/konfig" @@ -17,6 +16,7 @@ import ( "sigs.k8s.io/kustomize/api/provider" "sigs.k8s.io/kustomize/api/resmap" "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/kyaml/filesys" "sigs.k8s.io/kustomize/kyaml/openapi" ) @@ -90,19 +90,25 @@ func (b *Kustomizer) Run( return nil, err } if b.options.DoLegacyResourceSort { - builtins.NewLegacyOrderTransformerPlugin().Transform(m) + err = builtins.NewLegacyOrderTransformerPlugin().Transform(m) + if err != nil { + return nil, err + } } if b.options.AddManagedbyLabel { t := builtins.LabelTransformerPlugin{ Labels: map[string]string{ - konfig.ManagedbyLabelKey: fmt.Sprintf( - "kustomize-%s", provenance.GetProvenance().Semver())}, + konfig.ManagedbyLabelKey: fmt.Sprintf("kustomize-%s", provenance.GetProvenance().Semver()), + }, FieldSpecs: []types.FieldSpec{{ Path: "metadata/labels", CreateIfNotPresent: true, }}, } - t.Transform(m) + err = t.Transform(m) + if err != nil { + return nil, err + } } m.RemoveBuildAnnotations() return m, nil diff --git a/vendor/sigs.k8s.io/kustomize/api/loader/fileloader.go b/vendor/sigs.k8s.io/kustomize/api/loader/fileloader.go index e0fa2807f..92bfc3f69 100644 --- a/vendor/sigs.k8s.io/kustomize/api/loader/fileloader.go +++ b/vendor/sigs.k8s.io/kustomize/api/loader/fileloader.go @@ -12,9 +12,9 @@ import ( "path/filepath" "strings" - "sigs.k8s.io/kustomize/api/filesys" "sigs.k8s.io/kustomize/api/ifc" "sigs.k8s.io/kustomize/api/internal/git" + "sigs.k8s.io/kustomize/kyaml/filesys" ) // fileLoader is a kustomization's interface to files. diff --git a/vendor/sigs.k8s.io/kustomize/api/loader/loader.go b/vendor/sigs.k8s.io/kustomize/api/loader/loader.go index c72a95965..7a2b75f20 100644 --- a/vendor/sigs.k8s.io/kustomize/api/loader/loader.go +++ b/vendor/sigs.k8s.io/kustomize/api/loader/loader.go @@ -5,9 +5,9 @@ package loader import ( - "sigs.k8s.io/kustomize/api/filesys" "sigs.k8s.io/kustomize/api/ifc" "sigs.k8s.io/kustomize/api/internal/git" + "sigs.k8s.io/kustomize/kyaml/filesys" ) // NewLoader returns a Loader pointed at the given target. diff --git a/vendor/sigs.k8s.io/kustomize/api/loader/loadrestrictions.go b/vendor/sigs.k8s.io/kustomize/api/loader/loadrestrictions.go index 99b5562fb..a016a9625 100644 --- a/vendor/sigs.k8s.io/kustomize/api/loader/loadrestrictions.go +++ b/vendor/sigs.k8s.io/kustomize/api/loader/loadrestrictions.go @@ -6,7 +6,7 @@ package loader import ( "fmt" - "sigs.k8s.io/kustomize/api/filesys" + "sigs.k8s.io/kustomize/kyaml/filesys" ) type LoadRestrictorFunc func( diff --git a/vendor/sigs.k8s.io/kustomize/api/resmap/idslice.go b/vendor/sigs.k8s.io/kustomize/api/resmap/idslice.go index f2e46d440..a13d9d3c9 100644 --- a/vendor/sigs.k8s.io/kustomize/api/resmap/idslice.go +++ b/vendor/sigs.k8s.io/kustomize/api/resmap/idslice.go @@ -19,7 +19,7 @@ package resmap import ( "sort" - "sigs.k8s.io/kustomize/api/resid" + "sigs.k8s.io/kustomize/kyaml/resid" ) // IdSlice implements the sort interface. diff --git a/vendor/sigs.k8s.io/kustomize/api/resmap/resmap.go b/vendor/sigs.k8s.io/kustomize/api/resmap/resmap.go index 2b62482aa..704276cf1 100644 --- a/vendor/sigs.k8s.io/kustomize/api/resmap/resmap.go +++ b/vendor/sigs.k8s.io/kustomize/api/resmap/resmap.go @@ -7,9 +7,10 @@ package resmap import ( "sigs.k8s.io/kustomize/api/ifc" - "sigs.k8s.io/kustomize/api/resid" "sigs.k8s.io/kustomize/api/resource" "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/kyaml/kio" + "sigs.k8s.io/kustomize/kyaml/resid" "sigs.k8s.io/kustomize/kyaml/yaml" ) @@ -168,21 +169,20 @@ type ResMap interface { // GroupedByCurrentNamespace returns a map of namespace // to a slice of *Resource in that namespace. - // Resources for whom IsNamespaceableKind is false are - // are not included at all (see NonNamespaceable). + // Cluster-scoped Resources are not included (see ClusterScoped). // Resources with an empty namespace are placed // in the resid.DefaultNamespace entry. GroupedByCurrentNamespace() map[string][]*resource.Resource - // GroupByOrginalNamespace performs as GroupByNamespace + // GroupedByOriginalNamespace performs as GroupByNamespace // but use the original namespace instead of the current // one to perform the grouping. GroupedByOriginalNamespace() map[string][]*resource.Resource - // NonNamespaceable returns a slice of resources that + // ClusterScoped returns a slice of resources that // cannot be placed in a namespace, e.g. // Node, ClusterRole, Namespace itself, etc. - NonNamespaceable() []*resource.Resource + ClusterScoped() []*resource.Resource // AllIds returns all CurrentIds. AllIds() []resid.ResId @@ -254,4 +254,14 @@ type ResMap interface { // RemoveBuildAnnotations removes annotations created by the build process. RemoveBuildAnnotations() + + // ApplyFilter applies an RNode filter to all Resources in the ResMap. + // TODO: Send/recover ancillary Resource data to/from subprocesses. + // Assure that the ancillary data in Resource (everything not in the RNode) + // is sent to and re-captured from transformer subprocess (as the process + // might edit that information). One way to do this would be to solely use + // RNode metadata annotation reading and writing instead of using Resource + // struct data members, i.e. the Resource struct is replaced by RNode + // and use of (slow) k8s metadata annotations inside the RNode. + ApplyFilter(f kio.Filter) error } diff --git a/vendor/sigs.k8s.io/kustomize/api/resmap/reswrangler.go b/vendor/sigs.k8s.io/kustomize/api/resmap/reswrangler.go index acdceed23..0305a5532 100644 --- a/vendor/sigs.k8s.io/kustomize/api/resmap/reswrangler.go +++ b/vendor/sigs.k8s.io/kustomize/api/resmap/reswrangler.go @@ -6,11 +6,13 @@ package resmap import ( "bytes" "fmt" + "reflect" "github.com/pkg/errors" - "sigs.k8s.io/kustomize/api/resid" "sigs.k8s.io/kustomize/api/resource" "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/kyaml/kio" + "sigs.k8s.io/kustomize/kyaml/resid" kyaml "sigs.k8s.io/kustomize/kyaml/yaml" ) @@ -41,7 +43,7 @@ func (m *resWrangler) Clear() { func (m *resWrangler) DropEmpties() { var rList []*resource.Resource for _, r := range m.rList { - if !r.IsEmpty() { + if !r.IsNilOrEmpty() { rList = append(rList, r) } } @@ -228,18 +230,18 @@ func demandOneMatch( if len(r) > 1 { return nil, fmt.Errorf("multiple matches for %s %s", s, id) } - return nil, fmt.Errorf("no matches for %sId %s", s, id) + return nil, fmt.Errorf("no matches for %s %s", s, id) } -// GroupedByCurrentNamespace implements ResMap.GroupByCurrentNamespace +// GroupedByCurrentNamespace implements ResMap. func (m *resWrangler) GroupedByCurrentNamespace() map[string][]*resource.Resource { items := m.groupedByCurrentNamespace() delete(items, resid.TotallyNotANamespace) return items } -// NonNamespaceable implements ResMap.NonNamespaceable -func (m *resWrangler) NonNamespaceable() []*resource.Resource { +// ClusterScoped implements ResMap. +func (m *resWrangler) ClusterScoped() []*resource.Resource { return m.groupedByCurrentNamespace()[resid.TotallyNotANamespace] } @@ -255,7 +257,7 @@ func (m *resWrangler) groupedByCurrentNamespace() map[string][]*resource.Resourc return byNamespace } -// GroupedByNamespace implements ResMap.GroupByOrginalNamespace +// GroupedByOriginalNamespace implements ResMap. func (m *resWrangler) GroupedByOriginalNamespace() map[string][]*resource.Resource { items := m.groupedByOriginalNamespace() delete(items, resid.TotallyNotANamespace) @@ -323,7 +325,7 @@ func (m *resWrangler) ErrorIfNotEqualSets(other ResMap) error { "id in self matches %d in other; id: %s", len(others), id) } r2 := others[0] - if !r1.NodeEqual(r2) { + if !reflect.DeepEqual(r1.RNode, r2.RNode) { return fmt.Errorf( "nodes unequal: \n -- %s,\n -- %s\n\n--\n%#v\n------\n%#v\n", r1, r2, r1, r2) @@ -336,7 +338,7 @@ func (m *resWrangler) ErrorIfNotEqualSets(other ResMap) error { return nil } -// ErrorIfNotEqualList implements ResMap. +// ErrorIfNotEqualLists implements ResMap. func (m *resWrangler) ErrorIfNotEqualLists(other ResMap) error { m2, ok := other.(*resWrangler) if !ok { @@ -388,7 +390,7 @@ func (m *resWrangler) makeCopy(copier resCopier) ResMap { func (m *resWrangler) SubsetThatCouldBeReferencedByResource( referrer *resource.Resource) ResMap { referrerId := referrer.CurId() - if !referrerId.IsNamespaceableKind() { + if referrerId.IsClusterScoped() { // A cluster scoped resource can refer to anything. return m } @@ -396,7 +398,7 @@ func (m *resWrangler) SubsetThatCouldBeReferencedByResource( roleBindingNamespaces := getNamespacesForRoleBinding(referrer) for _, possibleTarget := range m.rList { id := possibleTarget.CurId() - if !id.IsNamespaceableKind() { + if id.IsClusterScoped() { // A cluster-scoped resource can be referred to by anything. result.append(possibleTarget) continue @@ -409,8 +411,7 @@ func (m *resWrangler) SubsetThatCouldBeReferencedByResource( // The two objects are namespaced (not cluster-scoped), AND // are in different namespaces. // There's still a chance they can refer to each other. - ns := possibleTarget.GetNamespace() - if roleBindingNamespaces[ns] { + if roleBindingNamespaces[possibleTarget.GetNamespace()] { result.append(possibleTarget) } } @@ -424,6 +425,7 @@ func getNamespacesForRoleBinding(r *resource.Resource) map[string]bool { if r.GetKind() != "RoleBinding" { return result } + //nolint staticcheck subjects, err := r.GetSlice("subjects") if err != nil || subjects == nil { return result @@ -586,7 +588,7 @@ func (m *resWrangler) Select(s types.Selector) ([]*resource.Resource, error) { func (m *resWrangler) ToRNodeSlice() []*kyaml.RNode { result := make([]*kyaml.RNode, len(m.rList)) for i := range m.rList { - result[i] = m.rList[i].AsRNode() + result[i] = m.rList[i].Copy() } return result } @@ -605,7 +607,7 @@ func (m *resWrangler) ApplySmPatch( return err } } - if !res.IsEmpty() { + if !res.IsNilOrEmpty() { list = append(list, res) } } @@ -618,3 +620,43 @@ func (m *resWrangler) RemoveBuildAnnotations() { r.RemoveBuildAnnotations() } } + +// ApplyFilter implements ResMap. +func (m *resWrangler) ApplyFilter(f kio.Filter) error { + reverseLookup := make(map[*kyaml.RNode]*resource.Resource, len(m.rList)) + nodes := make([]*kyaml.RNode, len(m.rList)) + for i, r := range m.rList { + ptr := &(r.RNode) + nodes[i] = ptr + reverseLookup[ptr] = r + } + // The filter can modify nodes, but also delete and create them. + // The filtered list might be smaller or larger than the nodes list. + filtered, err := f.Filter(nodes) + if err != nil { + return err + } + // Rebuild the resmap from the filtered RNodes. + var nRList []*resource.Resource + for _, rn := range filtered { + if rn.IsNilOrEmpty() { + // A node might make it through the filter as an object, + // but still be empty. Drop such entries. + continue + } + res, ok := reverseLookup[rn] + if !ok { + // A node was created; make a Resource to wrap it. + res = &resource.Resource{ + RNode: *rn, + // Leave remaining fields empty. + // At at time of writing, seeking to eliminate those fields. + // Alternatively, could just return error on creation attempt + // until remaining fields eliminated. + } + } + nRList = append(nRList, res) + } + m.rList = nRList + return nil +} diff --git a/vendor/sigs.k8s.io/kustomize/api/resource/factory.go b/vendor/sigs.k8s.io/kustomize/api/resource/factory.go index a9a1006bc..97ced84ba 100644 --- a/vendor/sigs.k8s.io/kustomize/api/resource/factory.go +++ b/vendor/sigs.k8s.io/kustomize/api/resource/factory.go @@ -13,15 +13,21 @@ import ( "sigs.k8s.io/kustomize/api/internal/generators" "sigs.k8s.io/kustomize/api/internal/kusterr" "sigs.k8s.io/kustomize/api/konfig" - "sigs.k8s.io/kustomize/api/resid" "sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/kustomize/kyaml/kio" + "sigs.k8s.io/kustomize/kyaml/resid" "sigs.k8s.io/kustomize/kyaml/yaml" ) // Factory makes instances of Resource. type Factory struct { hasher ifc.KustHasher + + // When set to true, IncludeLocalConfigs indicates + // that Factory should include resources with the + // annotation 'config.kubernetes.io/local-config'. + // By default these resources are ignored. + IncludeLocalConfigs bool } // NewFactory makes an instance of Factory. @@ -69,7 +75,7 @@ func (rf *Factory) makeOne(rn *yaml.RNode, o *types.GenArgs) *Resource { if o == nil { o = types.NewGenArgs(nil) } - return &Resource{node: rn, options: o} + return &Resource{RNode: *rn, options: o} } // SliceFromPatches returns a slice of resources given a patch path @@ -221,13 +227,15 @@ func (rf *Factory) shouldIgnore(n *yaml.RNode) (bool, error) { if n.IsNilOrEmpty() { return true, nil } - md, err := n.GetValidatedMetadata() - if err != nil { - return true, err - } - _, ignore := md.ObjectMeta.Annotations[konfig.IgnoredByKustomizeAnnotation] - if ignore { - return true, nil + if !rf.IncludeLocalConfigs { + md, err := n.GetValidatedMetadata() + if err != nil { + return true, err + } + _, ignore := md.ObjectMeta.Annotations[konfig.IgnoredByKustomizeAnnotation] + if ignore { + return true, nil + } } if foundNil, path := n.HasNilEntryInList(); foundNil { return true, fmt.Errorf("empty item at %v in object %v", path, n) diff --git a/vendor/sigs.k8s.io/kustomize/api/resource/idset.go b/vendor/sigs.k8s.io/kustomize/api/resource/idset.go index eaa253381..5d6bd63ed 100644 --- a/vendor/sigs.k8s.io/kustomize/api/resource/idset.go +++ b/vendor/sigs.k8s.io/kustomize/api/resource/idset.go @@ -3,7 +3,7 @@ package resource -import "sigs.k8s.io/kustomize/api/resid" +import "sigs.k8s.io/kustomize/kyaml/resid" type IdSet struct { ids map[resid.ResId]bool diff --git a/vendor/sigs.k8s.io/kustomize/api/resource/resource.go b/vendor/sigs.k8s.io/kustomize/api/resource/resource.go index f01779899..c7065a385 100644 --- a/vendor/sigs.k8s.io/kustomize/api/resource/resource.go +++ b/vendor/sigs.k8s.io/kustomize/api/resource/resource.go @@ -4,18 +4,16 @@ package resource import ( - "errors" "fmt" "log" - "reflect" "strings" "sigs.k8s.io/kustomize/api/filters/patchstrategicmerge" "sigs.k8s.io/kustomize/api/ifc" - "sigs.k8s.io/kustomize/api/konfig" - "sigs.k8s.io/kustomize/api/resid" + "sigs.k8s.io/kustomize/api/internal/utils" "sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/kustomize/kyaml/kio" + "sigs.k8s.io/kustomize/kyaml/resid" kyaml "sigs.k8s.io/kustomize/kyaml/yaml" "sigs.k8s.io/yaml" ) @@ -23,173 +21,37 @@ import ( // Resource is an RNode, representing a Kubernetes Resource Model object, // paired with metadata used by kustomize. type Resource struct { - // TODO: Inline RNode, dropping complexity. Resource is just a decorator. - node *kyaml.RNode + kyaml.RNode options *types.GenArgs refBy []resid.ResId refVarNames []string } -const ( - buildAnnotationPreviousKinds = konfig.ConfigAnnoDomain + "/previousKinds" - buildAnnotationPreviousNames = konfig.ConfigAnnoDomain + "/previousNames" - buildAnnotationPrefixes = konfig.ConfigAnnoDomain + "/prefixes" - buildAnnotationSuffixes = konfig.ConfigAnnoDomain + "/suffixes" - buildAnnotationPreviousNamespaces = konfig.ConfigAnnoDomain + "/previousNamespaces" - - // the following are only for patches, to specify whether they can change names - // and kinds of their targets - buildAnnotationAllowNameChange = konfig.ConfigAnnoDomain + "/allowNameChange" - buildAnnotationAllowKindChange = konfig.ConfigAnnoDomain + "/allowKindChange" -) - -var buildAnnotations = []string{ - buildAnnotationPreviousKinds, - buildAnnotationPreviousNames, - buildAnnotationPrefixes, - buildAnnotationSuffixes, - buildAnnotationPreviousNamespaces, - buildAnnotationAllowNameChange, - buildAnnotationAllowKindChange, +var BuildAnnotations = []string{ + utils.BuildAnnotationPreviousKinds, + utils.BuildAnnotationPreviousNames, + utils.BuildAnnotationPrefixes, + utils.BuildAnnotationSuffixes, + utils.BuildAnnotationPreviousNamespaces, + utils.BuildAnnotationAllowNameChange, + utils.BuildAnnotationAllowKindChange, } -func (r *Resource) AsRNode() *kyaml.RNode { - return r.node.Copy() -} - -func (r *Resource) ResetPrimaryData(incoming *Resource) { - r.node = incoming.node.Copy() -} - -func (r *Resource) GetAnnotations() map[string]string { - annotations, err := r.node.GetAnnotations() - if err != nil || annotations == nil { - return make(map[string]string) - } - return annotations -} - -func (r *Resource) GetFieldValue(f string) (interface{}, error) { - //nolint:staticcheck - return r.node.GetFieldValue(f) -} - -func (r *Resource) GetDataMap() map[string]string { - return r.node.GetDataMap() -} - -func (r *Resource) GetBinaryDataMap() map[string]string { - return r.node.GetBinaryDataMap() +func (r *Resource) ResetRNode(incoming *Resource) { + r.RNode = *incoming.Copy() } func (r *Resource) GetGvk() resid.Gvk { - meta, err := r.node.GetMeta() - if err != nil { - return resid.GvkFromString("") - } - g, v := resid.ParseGroupVersion(meta.APIVersion) - return resid.Gvk{Group: g, Version: v, Kind: meta.Kind} + return resid.GvkFromNode(&r.RNode) } func (r *Resource) Hash(h ifc.KustHasher) (string, error) { - return h.Hash(r.node) -} - -func (r *Resource) GetKind() string { - return r.node.GetKind() -} - -func (r *Resource) GetLabels() map[string]string { - l, err := r.node.GetLabels() - if err != nil { - return map[string]string{} - } - return l -} - -func (r *Resource) GetName() string { - return r.node.GetName() -} - -func (r *Resource) GetSlice(p string) ([]interface{}, error) { - //nolint:staticcheck - return r.node.GetSlice(p) -} - -func (r *Resource) GetString(p string) (string, error) { - //nolint:staticcheck - return r.node.GetString(p) -} - -func (r *Resource) IsEmpty() bool { - return r.node.IsNilOrEmpty() -} - -func (r *Resource) Map() (map[string]interface{}, error) { - return r.node.Map() -} - -func (r *Resource) MarshalJSON() ([]byte, error) { - return r.node.MarshalJSON() -} - -func (r *Resource) MatchesLabelSelector(selector string) (bool, error) { - return r.node.MatchesLabelSelector(selector) -} - -func (r *Resource) MatchesAnnotationSelector(selector string) (bool, error) { - return r.node.MatchesAnnotationSelector(selector) -} - -func (r *Resource) SetAnnotations(m map[string]string) { - if len(m) == 0 { - // Force field erasure. - r.node.SetAnnotations(nil) - return - } - r.node.SetAnnotations(m) -} - -func (r *Resource) SetDataMap(m map[string]string) { - r.node.SetDataMap(m) -} - -func (r *Resource) SetBinaryDataMap(m map[string]string) { - r.node.SetBinaryDataMap(m) + return h.Hash(&r.RNode) } func (r *Resource) SetGvk(gvk resid.Gvk) { - r.node.SetMapField( - kyaml.NewScalarRNode(gvk.Kind), kyaml.KindField) - r.node.SetMapField( - kyaml.NewScalarRNode(gvk.ApiVersion()), kyaml.APIVersionField) -} - -func (r *Resource) SetLabels(m map[string]string) { - if len(m) == 0 { - // Force field erasure. - r.node.SetLabels(nil) - return - } - r.node.SetLabels(m) -} - -func (r *Resource) SetName(n string) { - r.node.SetName(n) -} - -func (r *Resource) SetNamespace(n string) { - r.node.SetNamespace(n) -} - -func (r *Resource) SetKind(k string) { - gvk := r.GetGvk() - gvk.Kind = k - r.SetGvk(gvk) -} - -func (r *Resource) UnmarshalJSON(s []byte) error { - return r.node.UnmarshalJSON(s) + r.SetKind(gvk.Kind) + r.SetApiVersion(gvk.ApiVersion()) } // ResCtx is an interface describing the contextual added @@ -209,24 +71,36 @@ type ResCtxMatcher func(ResCtx) bool // DeepCopy returns a new copy of resource func (r *Resource) DeepCopy() *Resource { rc := &Resource{ - node: r.node.Copy(), + RNode: *r.Copy(), } - rc.copyOtherFields(r) + rc.copyKustomizeSpecificFields(r) return rc } -// CopyMergeMetaDataFields copies everything but the non-metadata in +// CopyMergeMetaDataFieldsFrom copies everything but the non-metadata in // the resource. -func (r *Resource) CopyMergeMetaDataFieldsFrom(other *Resource) { - r.SetLabels(mergeStringMaps(other.GetLabels(), r.GetLabels())) - r.SetAnnotations( - mergeStringMaps(other.GetAnnotations(), r.GetAnnotations())) - r.SetName(other.GetName()) - r.SetNamespace(other.GetNamespace()) - r.copyOtherFields(other) +// TODO: move to RNode, use GetMeta to improve performance. +// Must remove the kustomize bit at the end. +func (r *Resource) CopyMergeMetaDataFieldsFrom(other *Resource) error { + if err := r.SetLabels( + mergeStringMaps(other.GetLabels(), r.GetLabels())); err != nil { + return fmt.Errorf("copyMerge cannot set labels - %w", err) + } + if err := r.SetAnnotations( + mergeStringMaps(other.GetAnnotations(), r.GetAnnotations())); err != nil { + return fmt.Errorf("copyMerge cannot set annotations - %w", err) + } + if err := r.SetName(other.GetName()); err != nil { + return fmt.Errorf("copyMerge cannot set name - %w", err) + } + if err := r.SetNamespace(other.GetNamespace()); err != nil { + return fmt.Errorf("copyMerge cannot set namespace - %w", err) + } + r.copyKustomizeSpecificFields(other) + return nil } -func (r *Resource) copyOtherFields(other *Resource) { +func (r *Resource) copyKustomizeSpecificFields(other *Resource) { r.options = other.options r.refBy = other.copyRefBy() r.refVarNames = copyStringSlice(other.refVarNames) @@ -282,12 +156,6 @@ func (r *Resource) ReferencesEqual(other *Resource) bool { return len(setSelf) == len(setOther) } -// NodeEqual returns true if the resource's nodes are -// equal, ignoring ancillary information like genargs, refby, etc. -func (r *Resource) NodeEqual(o *Resource) bool { - return reflect.DeepEqual(r.node, o.node) -} - func (r *Resource) copyRefBy() []resid.ResId { if r.refBy == nil { return nil @@ -308,12 +176,12 @@ func copyStringSlice(s []string) []string { // Implements ResCtx AddNamePrefix func (r *Resource) AddNamePrefix(p string) { - r.appendCsvAnnotation(buildAnnotationPrefixes, p) + r.appendCsvAnnotation(utils.BuildAnnotationPrefixes, p) } // Implements ResCtx AddNameSuffix func (r *Resource) AddNameSuffix(s string) { - r.appendCsvAnnotation(buildAnnotationSuffixes, s) + r.appendCsvAnnotation(utils.BuildAnnotationSuffixes, s) } func (r *Resource) appendCsvAnnotation(name, value string) { @@ -326,33 +194,19 @@ func (r *Resource) appendCsvAnnotation(name, value string) { } else { annotations[name] = value } - r.SetAnnotations(annotations) -} - -func SameEndingSubarray(shortest, longest []string) bool { - if len(shortest) > len(longest) { - longest, shortest = shortest, longest + if err := r.SetAnnotations(annotations); err != nil { + panic(err) } - diff := len(longest) - len(shortest) - if len(shortest) == 0 { - return diff == 0 - } - for i := len(shortest) - 1; i >= 0; i-- { - if longest[i+diff] != shortest[i] { - return false - } - } - return true } // Implements ResCtx GetNamePrefixes func (r *Resource) GetNamePrefixes() []string { - return r.getCsvAnnotation(buildAnnotationPrefixes) + return r.getCsvAnnotation(utils.BuildAnnotationPrefixes) } // Implements ResCtx GetNameSuffixes func (r *Resource) GetNameSuffixes() []string { - return r.getCsvAnnotation(buildAnnotationSuffixes) + return r.getCsvAnnotation(utils.BuildAnnotationSuffixes) } func (r *Resource) getCsvAnnotation(name string) []string { @@ -367,7 +221,8 @@ func (r *Resource) getCsvAnnotation(name string) []string { // as OutermostPrefixSuffix but performs a deeper comparison // of the suffix and prefix slices. func (r *Resource) PrefixesSuffixesEquals(o ResCtx) bool { - return SameEndingSubarray(r.GetNamePrefixes(), o.GetNamePrefixes()) && SameEndingSubarray(r.GetNameSuffixes(), o.GetNameSuffixes()) + return utils.SameEndingSubSlice(r.GetNamePrefixes(), o.GetNamePrefixes()) && + utils.SameEndingSubSlice(r.GetNameSuffixes(), o.GetNameSuffixes()) } // RemoveBuildAnnotations removes annotations created by the build process. @@ -378,45 +233,49 @@ func (r *Resource) RemoveBuildAnnotations() { if len(annotations) == 0 { return } - for _, a := range buildAnnotations { + for _, a := range BuildAnnotations { delete(annotations, a) } - r.SetAnnotations(annotations) + if err := r.SetAnnotations(annotations); err != nil { + panic(err) + } } func (r *Resource) setPreviousId(ns string, n string, k string) *Resource { - r.appendCsvAnnotation(buildAnnotationPreviousNames, n) - r.appendCsvAnnotation(buildAnnotationPreviousNamespaces, ns) - r.appendCsvAnnotation(buildAnnotationPreviousKinds, k) + r.appendCsvAnnotation(utils.BuildAnnotationPreviousNames, n) + r.appendCsvAnnotation(utils.BuildAnnotationPreviousNamespaces, ns) + r.appendCsvAnnotation(utils.BuildAnnotationPreviousKinds, k) return r } -func (r *Resource) SetAllowNameChange(value string) { +// AllowNameChange allows name changes to the resource. +func (r *Resource) AllowNameChange() { annotations := r.GetAnnotations() - annotations[buildAnnotationAllowNameChange] = value - r.SetAnnotations(annotations) + annotations[utils.BuildAnnotationAllowNameChange] = utils.Allowed + if err := r.SetAnnotations(annotations); err != nil { + panic(err) + } } func (r *Resource) NameChangeAllowed() bool { annotations := r.GetAnnotations() - if allowed, set := annotations[buildAnnotationAllowNameChange]; set && allowed == "true" { - return true - } - return false + v, ok := annotations[utils.BuildAnnotationAllowNameChange] + return ok && v == utils.Allowed } -func (r *Resource) SetAllowKindChange(value string) { +// AllowKindChange allows kind changes to the resource. +func (r *Resource) AllowKindChange() { annotations := r.GetAnnotations() - annotations[buildAnnotationAllowKindChange] = value - r.SetAnnotations(annotations) + annotations[utils.BuildAnnotationAllowKindChange] = utils.Allowed + if err := r.SetAnnotations(annotations); err != nil { + panic(err) + } } func (r *Resource) KindChangeAllowed() bool { annotations := r.GetAnnotations() - if allowed, set := annotations[buildAnnotationAllowKindChange]; set && allowed == "true" { - return true - } - return false + v, ok := annotations[utils.BuildAnnotationAllowKindChange] + return ok && v == utils.Allowed } // String returns resource as JSON. @@ -463,13 +322,6 @@ func (r *Resource) NeedHashSuffix() bool { return r.options != nil && r.options.ShouldAddHashSuffixToName() } -// GetNamespace returns the namespace the resource thinks it's in. -func (r *Resource) GetNamespace() string { - namespace, _ := r.GetString("metadata.namespace") - // if err, namespace is empty, so no need to check. - return namespace -} - // OrgId returns the original, immutable ResId for the resource. // This doesn't have to be unique in a ResMap. func (r *Resource) OrgId() resid.ResId { @@ -487,26 +339,12 @@ func (r *Resource) OrgId() resid.ResId { // The returned array does not include the resource's current // ID. If there are no previous IDs, this will return nil. func (r *Resource) PrevIds() []resid.ResId { - var ids []resid.ResId - // TODO: merge previous names and namespaces into one list of - // pairs on one annotation so there is no chance of error - names := r.getCsvAnnotation(buildAnnotationPreviousNames) - ns := r.getCsvAnnotation(buildAnnotationPreviousNamespaces) - kinds := r.getCsvAnnotation(buildAnnotationPreviousKinds) - if len(names) != len(ns) || len(names) != len(kinds) { - panic(errors.New( - "number of previous names, " + - "number of previous namespaces, " + - "number of previous kinds not equal")) + prevIds, err := utils.PrevIds(&r.RNode) + if err != nil { + // this should never happen + panic(err) } - for i := range names { - k := kinds[i] - gvk := r.GetGvk() - gvk.Kind = k - ids = append(ids, resid.NewResIdWithNamespace( - gvk, names[i], ns[i])) - } - return ids + return prevIds } // StorePreviousId stores the resource's current ID via build annotations. @@ -550,11 +388,11 @@ func (r *Resource) ApplySmPatch(patch *Resource) error { r.StorePreviousId() } if err := r.ApplyFilter(patchstrategicmerge.Filter{ - Patch: patch.node, + Patch: &patch.RNode, }); err != nil { return err } - if r.IsEmpty() { + if r.IsNilOrEmpty() { return nil } if !patch.KindChangeAllowed() { @@ -568,10 +406,11 @@ func (r *Resource) ApplySmPatch(patch *Resource) error { } func (r *Resource) ApplyFilter(f kio.Filter) error { - l, err := f.Filter([]*kyaml.RNode{r.node}) + l, err := f.Filter([]*kyaml.RNode{&r.RNode}) if len(l) == 0 { - // The node was deleted. The following makes r.IsEmpty() true. - r.node = nil + // The node was deleted, which means the entire resource + // must be deleted. Signal that via the following: + r.SetYNode(nil) } return err } diff --git a/vendor/sigs.k8s.io/kustomize/api/types/fieldspec.go b/vendor/sigs.k8s.io/kustomize/api/types/fieldspec.go index 0bee70256..8d3579544 100644 --- a/vendor/sigs.k8s.io/kustomize/api/types/fieldspec.go +++ b/vendor/sigs.k8s.io/kustomize/api/types/fieldspec.go @@ -6,7 +6,7 @@ package types import ( "fmt" - "sigs.k8s.io/kustomize/api/resid" + "sigs.k8s.io/kustomize/kyaml/resid" ) // FieldSpec completely specifies a kustomizable field in a k8s API object. diff --git a/vendor/sigs.k8s.io/kustomize/api/types/genargs.go b/vendor/sigs.k8s.io/kustomize/api/types/genargs.go index a3229c8e3..586d7f1af 100644 --- a/vendor/sigs.k8s.io/kustomize/api/types/genargs.go +++ b/vendor/sigs.k8s.io/kustomize/api/types/genargs.go @@ -39,7 +39,7 @@ func (g *GenArgs) ShouldAddHashSuffixToName() bool { // Behavior returns Behavior field of GeneratorArgs func (g *GenArgs) Behavior() GenerationBehavior { - if g.args == nil { + if g == nil || g.args == nil { return BehaviorUnspecified } return NewGenerationBehavior(g.args.Behavior) diff --git a/vendor/sigs.k8s.io/kustomize/api/types/generatoroptions.go b/vendor/sigs.k8s.io/kustomize/api/types/generatoroptions.go index c30f6517d..683d89bfd 100644 --- a/vendor/sigs.k8s.io/kustomize/api/types/generatoroptions.go +++ b/vendor/sigs.k8s.io/kustomize/api/types/generatoroptions.go @@ -15,6 +15,9 @@ type GeneratorOptions struct { // suffix to the names of generated resources that is a hash of the // resource contents. DisableNameSuffixHash bool `json:"disableNameSuffixHash,omitempty" yaml:"disableNameSuffixHash,omitempty"` + + // Immutable if true add to all generated resources. + Immutable bool `json:"immutable,omitempty" yaml:"immutable,omitempty"` } // MergeGlobalOptionsIntoLocal merges two instances of GeneratorOptions. @@ -42,6 +45,9 @@ func MergeGlobalOptionsIntoLocal( if globalOpts.DisableNameSuffixHash { localOpts.DisableNameSuffixHash = true } + if globalOpts.Immutable { + localOpts.Immutable = true + } return localOpts } diff --git a/vendor/sigs.k8s.io/kustomize/api/types/helmchartargs.go b/vendor/sigs.k8s.io/kustomize/api/types/helmchartargs.go index 7bb22f2e4..c0fff2457 100644 --- a/vendor/sigs.k8s.io/kustomize/api/types/helmchartargs.go +++ b/vendor/sigs.k8s.io/kustomize/api/types/helmchartargs.go @@ -51,6 +51,10 @@ type HelmChart struct { // If omitted, the flag --generate-name is passed to 'helm template'. ReleaseName string `json:"releaseName,omitempty" yaml:"releaseName,omitempty"` + // Namespace set the target namespace for a release. It is .Release.Namespace + // in the helm template + Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` + // ValuesFile is local file path to a values file to use _instead of_ // the default values that accompanied the chart. // The default values are in '{ChartHome}/{Name}/values.yaml'. @@ -64,6 +68,10 @@ type HelmChart struct { // Legal values: 'merge', 'override', 'replace'. // Defaults to 'override'. ValuesMerge string `json:"valuesMerge,omitempty" yaml:"valuesMerge,omitempty"` + + // IncludeCRDs specifies if Helm should also generate CustomResourceDefinitions. + // Defaults to 'false'. + IncludeCRDs bool `json:"includeCRDs,omitempty" yaml:"includeCRDs,omitempty"` } // HelmChartArgs contains arguments to helm. diff --git a/vendor/sigs.k8s.io/kustomize/api/types/iampolicygenerator.go b/vendor/sigs.k8s.io/kustomize/api/types/iampolicygenerator.go new file mode 100644 index 000000000..f1d27ba7b --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/api/types/iampolicygenerator.go @@ -0,0 +1,36 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package types + +type Cloud string + +const GKE Cloud = "gke" + +// IAMPolicyGeneratorArgs contains arguments to generate a GKE service account resource. +type IAMPolicyGeneratorArgs struct { + // which cloud provider to generate for (e.g. "gke") + Cloud `json:"cloud" yaml:"cloud"` + + // information about the kubernetes cluster for this object + KubernetesService `json:"kubernetesService" yaml:"kubernetesService"` + + // information about the service account and project + ServiceAccount `json:"serviceAccount" yaml:"serviceAccount"` +} + +type KubernetesService struct { + // the name used for the Kubernetes service account + Name string `json:"name" yaml:"name"` + + // the name of the Kubernetes namespace for this object + Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` +} + +type ServiceAccount struct { + // the name of the new cloud provider service account + Name string `json:"name" yaml:"name"` + + // The ID of the project + ProjectId string `json:"projectId" yaml:"projectId"` +} diff --git a/vendor/sigs.k8s.io/kustomize/api/types/kustomization.go b/vendor/sigs.k8s.io/kustomize/api/types/kustomization.go index 9c555a860..8f4b45d1c 100644 --- a/vendor/sigs.k8s.io/kustomize/api/types/kustomization.go +++ b/vendor/sigs.k8s.io/kustomize/api/types/kustomization.go @@ -74,6 +74,10 @@ type Kustomization struct { // patch, but this operator is simpler to specify. Images []Image `json:"images,omitempty" yaml:"images,omitempty"` + // Replacements is a list of replacements, which will copy nodes from a + // specified source to N specified targets. + Replacements []ReplacementField `json:"replacements,omitempty" yaml:"replacements,omitempty"` + // Replicas is a list of {resourcename, count} that allows for simpler replica // specification. This can also be done with a patch. Replicas []Replica `json:"replicas,omitempty" yaml:"replicas,omitempty"` diff --git a/vendor/sigs.k8s.io/kustomize/api/types/pluginrestrictions.go b/vendor/sigs.k8s.io/kustomize/api/types/pluginrestrictions.go index 6dae63a97..b1ab2221f 100644 --- a/vendor/sigs.k8s.io/kustomize/api/types/pluginrestrictions.go +++ b/vendor/sigs.k8s.io/kustomize/api/types/pluginrestrictions.go @@ -42,7 +42,7 @@ const ( BploLoadFromFileSys ) -// FnPluginLoadingOptions set way functions-based pluing are restricted +// FnPluginLoadingOptions set way functions-based plugins are restricted type FnPluginLoadingOptions struct { // Allow to run executables EnableExec bool @@ -55,4 +55,6 @@ type FnPluginLoadingOptions struct { Mounts []string // list of env variables to pass to fn Env []string + // Run as uid and gid of the command executor + AsCurrentUser bool } diff --git a/vendor/sigs.k8s.io/kustomize/api/types/replacement.go b/vendor/sigs.k8s.io/kustomize/api/types/replacement.go index 41bd848a3..1f59239d9 100644 --- a/vendor/sigs.k8s.io/kustomize/api/types/replacement.go +++ b/vendor/sigs.k8s.io/kustomize/api/types/replacement.go @@ -3,6 +3,13 @@ package types +import ( + "fmt" + "strings" + + "sigs.k8s.io/kustomize/kyaml/resid" +) + const DefaultReplacementFieldPath = "metadata.name" // Replacement defines how to perform a substitution @@ -18,13 +25,27 @@ type Replacement struct { // SourceSelector is the source of the replacement transformer. type SourceSelector struct { // A specific object to read it from. - KrmId `json:",inline,omitempty" yaml:",inline,omitempty"` + resid.ResId `json:",inline,omitempty" yaml:",inline,omitempty"` // Structured field path expected in the allowed object. - FieldPath string `json:"fieldPath" yaml:"fieldPath"` + FieldPath string `json:"fieldPath,omitempty" yaml:"fieldPath,omitempty"` // Used to refine the interpretation of the field. - Options *FieldOptions `json:"options" yaml:"options"` + Options *FieldOptions `json:"options,omitempty" yaml:"options,omitempty"` +} + +func (s *SourceSelector) String() string { + if s == nil { + return "" + } + result := []string{s.ResId.String()} + if s.FieldPath != "" { + result = append(result, s.FieldPath) + } + if opts := s.Options.String(); opts != "" { + result = append(result, opts) + } + return strings.Join(result, ":") } // TargetSelector specifies fields in one or more objects. @@ -33,27 +54,34 @@ type TargetSelector struct { Select *Selector `json:"select" yaml:"select"` // From the allowed set, remove objects that match this. - Reject []*Selector `json:"reject" yaml:"reject"` + Reject []*Selector `json:"reject,omitempty" yaml:"reject,omitempty"` // Structured field paths expected in each allowed object. - FieldPaths []string `json:"fieldPaths" yaml:"fieldPaths"` + FieldPaths []string `json:"fieldPaths,omitempty" yaml:"fieldPaths,omitempty"` // Used to refine the interpretation of the field. - Options *FieldOptions `json:"options" yaml:"options"` + Options *FieldOptions `json:"options,omitempty" yaml:"options,omitempty"` } // FieldOptions refine the interpretation of FieldPaths. type FieldOptions struct { // Used to split/join the field. - Delimiter string `json:"delimiter" yaml:"delimiter"` + Delimiter string `json:"delimiter,omitempty" yaml:"delimiter,omitempty"` // Which position in the split to consider. - Index int `json:"index" yaml:"index"` + Index int `json:"index,omitempty" yaml:"index,omitempty"` // TODO (#3492): Implement use of this option // None, Base64, URL, Hex, etc - Encoding string `json:"encoding" yaml:"encoding"` + Encoding string `json:"encoding,omitempty" yaml:"encoding,omitempty"` // If field missing, add it. - Create bool `json:"create" yaml:"create"` + Create bool `json:"create,omitempty" yaml:"create,omitempty"` +} + +func (fo *FieldOptions) String() string { + if fo == nil || (fo.Delimiter == "" && !fo.Create) { + return "" + } + return fmt.Sprintf("%s(%d), create=%t", fo.Delimiter, fo.Index, fo.Create) } diff --git a/vendor/sigs.k8s.io/kustomize/api/types/replacementfield.go b/vendor/sigs.k8s.io/kustomize/api/types/replacementfield.go new file mode 100644 index 000000000..a5684f848 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/api/types/replacementfield.go @@ -0,0 +1,6 @@ +package types + +type ReplacementField struct { + Replacement `json:",inline,omitempty" yaml:",inline,omitempty"` + Path string `json:"path,omitempty" yaml:"path,omitempty"` +} diff --git a/vendor/sigs.k8s.io/kustomize/api/types/selector.go b/vendor/sigs.k8s.io/kustomize/api/types/selector.go index 4b7295c6a..2c07f0b01 100644 --- a/vendor/sigs.k8s.io/kustomize/api/types/selector.go +++ b/vendor/sigs.k8s.io/kustomize/api/types/selector.go @@ -4,17 +4,18 @@ package types import ( + "fmt" "regexp" - "sigs.k8s.io/kustomize/api/resid" + "sigs.k8s.io/kustomize/kyaml/resid" ) // Selector specifies a set of resources. // Any resource that matches intersection of all conditions // is included in this set. type Selector struct { - // KrmId refers to a GVKN/Ns of a resource. - KrmId `json:",inline,omitempty" yaml:",inline,omitempty"` + // ResId refers to a GVKN/Ns of a resource. + resid.ResId `json:",inline,omitempty" yaml:",inline,omitempty"` // AnnotationSelector is a string that follows the label selection expression // https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api @@ -27,21 +28,13 @@ type Selector struct { LabelSelector string `json:"labelSelector,omitempty" yaml:"labelSelector,omitempty"` } -// KrmId refers to a GVKN/Ns of a resource. -type KrmId struct { - resid.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"` - Name string `json:"name,omitempty" yaml:"name,omitempty"` - Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` +func (s *Selector) Copy() Selector { + return *s } -// Match returns true if id selects other, i.e. id's fields -// either match other's or are empty -func (id *KrmId) Match(other *KrmId) bool { - return (id.Group == "" || id.Group == other.Group) && - (id.Version == "" || id.Version == other.Version) && - (id.Kind == "" || id.Kind == other.Kind) && - (id.Name == "" || id.Name == other.Name) && - (id.Namespace == "" || id.Namespace == other.Namespace) +func (s *Selector) String() string { + return fmt.Sprintf( + "%s:a=%s:l=%s", s.ResId, s.AnnotationSelector, s.LabelSelector) } // SelectorRegex is a Selector with regex in GVK diff --git a/vendor/sigs.k8s.io/kustomize/api/types/var.go b/vendor/sigs.k8s.io/kustomize/api/types/var.go index a95315166..0ca5579c0 100644 --- a/vendor/sigs.k8s.io/kustomize/api/types/var.go +++ b/vendor/sigs.k8s.io/kustomize/api/types/var.go @@ -9,7 +9,7 @@ import ( "sort" "strings" - "sigs.k8s.io/kustomize/api/resid" + "sigs.k8s.io/kustomize/kyaml/resid" ) // Var represents a variable whose value will be sourced diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/comments/comments.go b/vendor/sigs.k8s.io/kustomize/kyaml/comments/comments.go index 9d6dc22dc..0dfc4d8de 100644 --- a/vendor/sigs.k8s.io/kustomize/kyaml/comments/comments.go +++ b/vendor/sigs.k8s.io/kustomize/kyaml/comments/comments.go @@ -54,7 +54,10 @@ func (c *copier) VisitList(s walk.Sources, _ *openapi.ResourceSchema, _ walk.Lis origin := originItems[i] if dest.Value == origin.Value { - copy(yaml.NewRNode(dest), yaml.NewRNode(origin)) + // We copy the comments recursively on each node in the list. + if err := CopyComments(yaml.NewRNode(dest), yaml.NewRNode(origin)); err != nil { + return nil, err + } } } diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/fieldmeta/fieldmeta.go b/vendor/sigs.k8s.io/kustomize/kyaml/fieldmeta/fieldmeta.go index 83fdff3d5..c537c3372 100644 --- a/vendor/sigs.k8s.io/kustomize/kyaml/fieldmeta/fieldmeta.go +++ b/vendor/sigs.k8s.io/kustomize/kyaml/fieldmeta/fieldmeta.go @@ -10,7 +10,7 @@ import ( "strconv" "strings" - "github.com/go-openapi/spec" + "k8s.io/kube-openapi/pkg/validation/spec" "sigs.k8s.io/kustomize/kyaml/errors" "sigs.k8s.io/kustomize/kyaml/openapi" "sigs.k8s.io/kustomize/kyaml/yaml" diff --git a/vendor/sigs.k8s.io/kustomize/api/filesys/confirmeddir.go b/vendor/sigs.k8s.io/kustomize/kyaml/filesys/confirmeddir.go similarity index 100% rename from vendor/sigs.k8s.io/kustomize/api/filesys/confirmeddir.go rename to vendor/sigs.k8s.io/kustomize/kyaml/filesys/confirmeddir.go diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/filesys/doc.go b/vendor/sigs.k8s.io/kustomize/kyaml/filesys/doc.go new file mode 100644 index 000000000..bd3963441 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/kyaml/filesys/doc.go @@ -0,0 +1,7 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +// Package filesys provides a file system abstraction, +// a subset of that provided by golang.org/pkg/os, +// with an on-disk and in-memory representation. +package filesys diff --git a/vendor/sigs.k8s.io/kustomize/api/filesys/file.go b/vendor/sigs.k8s.io/kustomize/kyaml/filesys/file.go similarity index 100% rename from vendor/sigs.k8s.io/kustomize/api/filesys/file.go rename to vendor/sigs.k8s.io/kustomize/kyaml/filesys/file.go diff --git a/vendor/sigs.k8s.io/kustomize/api/filesys/fileinfo.go b/vendor/sigs.k8s.io/kustomize/kyaml/filesys/fileinfo.go similarity index 100% rename from vendor/sigs.k8s.io/kustomize/api/filesys/fileinfo.go rename to vendor/sigs.k8s.io/kustomize/kyaml/filesys/fileinfo.go diff --git a/vendor/sigs.k8s.io/kustomize/api/filesys/fileondisk.go b/vendor/sigs.k8s.io/kustomize/kyaml/filesys/fileondisk.go similarity index 100% rename from vendor/sigs.k8s.io/kustomize/api/filesys/fileondisk.go rename to vendor/sigs.k8s.io/kustomize/kyaml/filesys/fileondisk.go diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/filesys/filesystem.go b/vendor/sigs.k8s.io/kustomize/kyaml/filesys/filesystem.go new file mode 100644 index 000000000..53e0f1921 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/kyaml/filesys/filesystem.go @@ -0,0 +1,120 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package filesys + +import ( + "path/filepath" +) + +const ( + Separator = string(filepath.Separator) + SelfDir = "." + ParentDir = ".." +) + +// FileSystem groups basic os filesystem methods. +// It's supposed be functional subset of https://golang.org/pkg/os +type FileSystem interface { + // Create a file. + Create(path string) (File, error) + // MkDir makes a directory. + Mkdir(path string) error + // MkDirAll makes a directory path, creating intervening directories. + MkdirAll(path string) error + // RemoveAll removes path and any children it contains. + RemoveAll(path string) error + // Open opens the named file for reading. + Open(path string) (File, error) + // IsDir returns true if the path is a directory. + IsDir(path string) bool + // ReadDir returns a list of files and directories within a directory. + ReadDir(path string) ([]string, error) + // CleanedAbs converts the given path into a + // directory and a file name, where the directory + // is represented as a ConfirmedDir and all that implies. + // If the entire path is a directory, the file component + // is an empty string. + CleanedAbs(path string) (ConfirmedDir, string, error) + // Exists is true if the path exists in the file system. + Exists(path string) bool + // Glob returns the list of matching files, + // emulating https://golang.org/pkg/path/filepath/#Glob + Glob(pattern string) ([]string, error) + // ReadFile returns the contents of the file at the given path. + ReadFile(path string) ([]byte, error) + // WriteFile writes the data to a file at the given path, + // overwriting anything that's already there. + WriteFile(path string, data []byte) error + // Walk walks the file system with the given WalkFunc. + Walk(path string, walkFn filepath.WalkFunc) error +} + +// FileSystemOrOnDisk satisfies the FileSystem interface by forwarding +// all of its method calls to the given FileSystem whenever it's not nil. +// If it's nil, the call is forwarded to the OS's underlying file system. +type FileSystemOrOnDisk struct { + FileSystem FileSystem +} + +// Set sets the given FileSystem as the target for all the FileSystem method calls. +func (fs *FileSystemOrOnDisk) Set(f FileSystem) { fs.FileSystem = f } + +func (fs FileSystemOrOnDisk) fs() FileSystem { + if fs.FileSystem != nil { + return fs.FileSystem + } + return MakeFsOnDisk() +} + +func (fs FileSystemOrOnDisk) Create(path string) (File, error) { + return fs.fs().Create(path) +} + +func (fs FileSystemOrOnDisk) Mkdir(path string) error { + return fs.fs().Mkdir(path) +} + +func (fs FileSystemOrOnDisk) MkdirAll(path string) error { + return fs.fs().MkdirAll(path) +} + +func (fs FileSystemOrOnDisk) RemoveAll(path string) error { + return fs.fs().RemoveAll(path) +} + +func (fs FileSystemOrOnDisk) Open(path string) (File, error) { + return fs.fs().Open(path) +} + +func (fs FileSystemOrOnDisk) IsDir(path string) bool { + return fs.fs().IsDir(path) +} + +func (fs FileSystemOrOnDisk) ReadDir(path string) ([]string, error) { + return fs.fs().ReadDir(path) +} + +func (fs FileSystemOrOnDisk) CleanedAbs(path string) (ConfirmedDir, string, error) { + return fs.fs().CleanedAbs(path) +} + +func (fs FileSystemOrOnDisk) Exists(path string) bool { + return fs.fs().Exists(path) +} + +func (fs FileSystemOrOnDisk) Glob(pattern string) ([]string, error) { + return fs.fs().Glob(pattern) +} + +func (fs FileSystemOrOnDisk) ReadFile(path string) ([]byte, error) { + return fs.fs().ReadFile(path) +} + +func (fs FileSystemOrOnDisk) WriteFile(path string, data []byte) error { + return fs.fs().WriteFile(path, data) +} + +func (fs FileSystemOrOnDisk) Walk(path string, walkFn filepath.WalkFunc) error { + return fs.fs().Walk(path, walkFn) +} diff --git a/vendor/sigs.k8s.io/kustomize/api/filesys/fsnode.go b/vendor/sigs.k8s.io/kustomize/kyaml/filesys/fsnode.go similarity index 80% rename from vendor/sigs.k8s.io/kustomize/api/filesys/fsnode.go rename to vendor/sigs.k8s.io/kustomize/kyaml/filesys/fsnode.go index e81c3df78..fbede9ed7 100644 --- a/vendor/sigs.k8s.io/kustomize/api/filesys/fsnode.go +++ b/vendor/sigs.k8s.io/kustomize/kyaml/filesys/fsnode.go @@ -6,6 +6,7 @@ package filesys import ( "bytes" "fmt" + "io" "log" "os" "path/filepath" @@ -37,9 +38,9 @@ type fsNode struct { // if this node is a file, this is the content. content []byte - // if this node is a file, this tracks whether or - // not it is "open". - open bool + // if offset is not nil the file is open and it tracks + // the current file offset. + offset *int } // MakeEmptyDirInMemory returns an empty directory. @@ -119,6 +120,9 @@ func (n *fsNode) addFile(name string, c []byte) (result *fsNode, err error) { result, ok := parent.dir[fileName] if ok { // File already exists; overwrite it. + if result.offset != nil { + return nil, fmt.Errorf("cannot add already opened file '%s'", n.Path()) + } result.content = c return result, nil } @@ -133,7 +137,12 @@ func (n *fsNode) addFile(name string, c []byte) (result *fsNode, err error) { // Create implements FileSystem. // Create makes an empty file. func (n *fsNode) Create(path string) (result File, err error) { - return n.AddFile(path, []byte{}) + f, err := n.AddFile(path, nil) + if err != nil { + return f, err + } + f.offset = new(int) + return f, nil } // WriteFile implements FileSystem. @@ -154,6 +163,7 @@ func (n *fsNode) AddFile( } func (n *fsNode) addDir(path string) (result *fsNode, err error) { + parent := n dName, subDirName := mySplit(path) if dName != "" { @@ -226,7 +236,7 @@ func (n *fsNode) CleanedAbs(path string) (ConfirmedDir, string, error) { return "", "", errors.Wrap(err, "unable to clean") } if node == nil { - return "", "", fmt.Errorf("'%s' doesn't exist", path) + return "", "", notExistError(path) } if node.isNodeADir() { return ConfirmedDir(node.Path()), "", nil @@ -299,7 +309,8 @@ func (n *fsNode) RemoveAll(path string) error { return err } if result == nil { - return fmt.Errorf("cannot find '%s' to remove it", path) + // If the path doesn't exist, no need to remove anything. + return nil } return result.Remove() } @@ -339,6 +350,32 @@ func (n *fsNode) IsDir(path string) bool { return result.isNodeADir() } +// ReadDir implements FileSystem. +func (n *fsNode) ReadDir(path string) ([]string, error) { + if !n.Exists(path) { + return nil, notExistError(path) + } + if !n.IsDir(path) { + return nil, fmt.Errorf("%s is not a directory", path) + } + + dir, err := n.Find(path) + if err != nil { + return nil, err + } + if dir == nil { + return nil, fmt.Errorf("could not find directory %s", path) + } + + keys := make([]string, len(dir.dir)) + i := 0 + for k := range dir.dir { + keys[i] = k + i++ + } + return keys, nil +} + // Size returns the size of the node. func (n *fsNode) Size() int64 { if n.isNodeADir() { @@ -348,22 +385,38 @@ func (n *fsNode) Size() int64 { } // Open implements FileSystem. -// Open opens the node for reading (just marks it). +// Open opens the node in read-write mode and sets the offset its start. +// Writing right after opening the file will replace the original content +// and move the offset forward, as with a file opened with O_RDWR | O_CREATE. +// +// As an example, let's consider a file with content "content": +// - open: sets offset to start, content is "content" +// - write "@": offset increases by one, the content is now "@ontent" +// - read the rest: since offset is 1, the read operation returns "ontent" +// - write "$": offset is at EOF, so "$" is appended and content is now "@ontent$" +// - read the rest: returns 0 bytes and EOF +// - close: the content is still "@ontent$" func (n *fsNode) Open(path string) (File, error) { result, err := n.Find(path) if err != nil { return nil, err } if result == nil { - return nil, fmt.Errorf("cannot find '%s' to open it", path) + return nil, notExistError(path) } - result.open = true + if result.offset != nil { + return nil, fmt.Errorf("cannot open previously opened file '%s'", path) + } + result.offset = new(int) return result, nil } // Close marks the node closed. func (n *fsNode) Close() error { - n.open = false + if n.offset == nil { + return fmt.Errorf("cannot close already closed file '%s'", n.Path()) + } + n.offset = nil return nil } @@ -374,11 +427,14 @@ func (n *fsNode) ReadFile(path string) (c []byte, err error) { return nil, err } if result == nil { - return nil, fmt.Errorf("cannot find '%s' to read it", path) + return nil, notExistError(path) + } + if result.isNodeADir() { + return nil, fmt.Errorf("cannot read content from non-file '%s'", n.Path()) } c = make([]byte, len(result.content)) - _, err = result.Read(c) - return c, err + copy(c, result.content) + return c, nil } // Read returns the content of the file node. @@ -387,7 +443,19 @@ func (n *fsNode) Read(d []byte) (c int, err error) { return 0, fmt.Errorf( "cannot read content from non-file '%s'", n.Path()) } - return copy(d, n.content), nil + if n.offset == nil { + return 0, fmt.Errorf("cannot read from closed file '%s'", n.Path()) + } + + rest := n.content[*n.offset:] + if len(d) < len(rest) { + rest = rest[:len(d)] + } else { + err = io.EOF + } + copy(d, rest) + *n.offset += len(rest) + return len(rest), err } // Write saves the contents of the argument to the file node. @@ -396,8 +464,12 @@ func (n *fsNode) Write(p []byte) (c int, err error) { return 0, fmt.Errorf( "cannot write content to non-file '%s'", n.Path()) } - n.content = make([]byte, len(p)) - return copy(n.content, p), nil + if n.offset == nil { + return 0, fmt.Errorf("cannot write to closed file '%s'", n.Path()) + } + n.content = append(n.content[:*n.offset], p...) + *n.offset = len(n.content) + return len(p), nil } // ContentMatches returns true if v matches fake file's content. @@ -422,7 +494,7 @@ func (n *fsNode) Walk(path string, walkFn filepath.WalkFunc) error { return err } if result == nil { - return fmt.Errorf("cannot find '%s' to walk it", path) + return notExistError(path) } return result.WalkMe(walkFn) } @@ -515,7 +587,7 @@ func isLegalFileNameForCreation(n string) bool { func (n *fsNode) RegExpGlob(pattern string) ([]string, error) { var result []string var expression = regexp.MustCompile(pattern) - n.WalkMe(func(path string, info os.FileInfo, err error) error { + err := n.WalkMe(func(path string, info os.FileInfo, err error) error { if err != nil { return err } @@ -526,6 +598,9 @@ func (n *fsNode) RegExpGlob(pattern string) ([]string, error) { } return nil }) + if err != nil { + return nil, err + } sort.Strings(result) return result, nil } @@ -537,7 +612,7 @@ func (n *fsNode) RegExpGlob(pattern string) ([]string, error) { // This is how /bin/ls behaves. func (n *fsNode) Glob(pattern string) ([]string, error) { var result []string - n.WalkMe(func(path string, info os.FileInfo, err error) error { + err := n.WalkMe(func(path string, info os.FileInfo, err error) error { if err != nil { return err } @@ -552,6 +627,16 @@ func (n *fsNode) Glob(pattern string) ([]string, error) { } return nil }) + if err != nil { + return nil, err + } sort.Strings(result) return result, nil } + +// notExistError indicates that a file or directory does not exist. +// Unwrapping returns os.ErrNotExist so errors.Is(err, os.ErrNotExist) works correctly. +type notExistError string + +func (err notExistError) Error() string { return fmt.Sprintf("'%s' doesn't exist", string(err)) } +func (err notExistError) Unwrap() error { return os.ErrNotExist } diff --git a/vendor/sigs.k8s.io/kustomize/api/filesys/fsondisk.go b/vendor/sigs.k8s.io/kustomize/kyaml/filesys/fsondisk.go similarity index 89% rename from vendor/sigs.k8s.io/kustomize/api/filesys/fsondisk.go rename to vendor/sigs.k8s.io/kustomize/kyaml/filesys/fsondisk.go index 6becbb6f1..d5c07f381 100644 --- a/vendor/sigs.k8s.io/kustomize/api/filesys/fsondisk.go +++ b/vendor/sigs.k8s.io/kustomize/kyaml/filesys/fsondisk.go @@ -57,7 +57,7 @@ func (x fsOnDisk) CleanedAbs( deLinked, err := filepath.EvalSymlinks(absRoot) if err != nil { return "", "", fmt.Errorf( - "evalsymlink failure on '%s' : %v", path, err) + "evalsymlink failure on '%s' : %w", path, err) } if x.IsDir(deLinked) { return ConfirmedDir(deLinked), "", nil @@ -100,6 +100,19 @@ func (fsOnDisk) IsDir(name string) bool { return info.IsDir() } +// ReadDir delegates to os.ReadDir +func (fsOnDisk) ReadDir(name string) ([]string, error) { + dirEntries, err := os.ReadDir(name) + if err != nil { + return nil, err + } + result := make([]string, len(dirEntries)) + for i := range dirEntries { + result[i] = dirEntries[i].Name() + } + return result, nil +} + // ReadFile delegates to ioutil.ReadFile. func (fsOnDisk) ReadFile(name string) ([]byte, error) { return ioutil.ReadFile(name) } diff --git a/vendor/sigs.k8s.io/kustomize/api/filesys/util.go b/vendor/sigs.k8s.io/kustomize/kyaml/filesys/util.go similarity index 100% rename from vendor/sigs.k8s.io/kustomize/api/filesys/util.go rename to vendor/sigs.k8s.io/kustomize/kyaml/filesys/util.go diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/fn/runtime/runtimeutil/runtimeutil.go b/vendor/sigs.k8s.io/kustomize/kyaml/fn/runtime/runtimeutil/runtimeutil.go index 29e2ea0ad..2454aa4cb 100644 --- a/vendor/sigs.k8s.io/kustomize/kyaml/fn/runtime/runtimeutil/runtimeutil.go +++ b/vendor/sigs.k8s.io/kustomize/kyaml/fn/runtime/runtimeutil/runtimeutil.go @@ -42,7 +42,7 @@ type FunctionFilter struct { DeferFailure bool // results saves the results emitted from Run - results *yaml.RNode + Results *yaml.RNode // exit saves the error returned from Run exit error @@ -250,7 +250,7 @@ func (c *FunctionFilter) doResults(r *kio.ByteReader) error { } if r.Results != nil { - c.results = r.Results + c.Results = r.Results } return nil } diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/LICENSE b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/LICENSE new file mode 100644 index 000000000..2683e4bb1 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/LICENSE @@ -0,0 +1,50 @@ + +This project is covered by two different licenses: MIT and Apache. + +#### MIT License #### + +The following files were ported to Go from C files of libyaml, and thus +are still covered by their original MIT license, with the additional +copyright staring in 2011 when the project was ported over: + + apic.go emitterc.go parserc.go readerc.go scannerc.go + writerc.go yamlh.go yamlprivateh.go + +Copyright (c) 2006-2010 Kirill Simonov +Copyright (c) 2006-2011 Kirill Simonov + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +### Apache License ### + +All the remaining project files are covered by the Apache license: + +Copyright (c) 2011-2019 Canonical Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/NOTICE b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/NOTICE new file mode 100644 index 000000000..866d74a7a --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/NOTICE @@ -0,0 +1,13 @@ +Copyright 2011-2016 Canonical Ltd. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/README.md b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/README.md new file mode 100644 index 000000000..08eb1babd --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/README.md @@ -0,0 +1,150 @@ +# YAML support for the Go language + +Introduction +------------ + +The yaml package enables Go programs to comfortably encode and decode YAML +values. It was developed within [Canonical](https://www.canonical.com) as +part of the [juju](https://juju.ubuntu.com) project, and is based on a +pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) +C library to parse and generate YAML data quickly and reliably. + +Compatibility +------------- + +The yaml package supports most of YAML 1.2, but preserves some behavior +from 1.1 for backwards compatibility. + +Specifically, as of v3 of the yaml package: + + - YAML 1.1 bools (_yes/no, on/off_) are supported as long as they are being + decoded into a typed bool value. Otherwise they behave as a string. Booleans + in YAML 1.2 are _true/false_ only. + - Octals encode and decode as _0777_ per YAML 1.1, rather than _0o777_ + as specified in YAML 1.2, because most parsers still use the old format. + Octals in the _0o777_ format are supported though, so new files work. + - Does not support base-60 floats. These are gone from YAML 1.2, and were + actually never supported by this package as it's clearly a poor choice. + +and offers backwards +compatibility with YAML 1.1 in some cases. +1.2, including support for +anchors, tags, map merging, etc. Multi-document unmarshalling is not yet +implemented, and base-60 floats from YAML 1.1 are purposefully not +supported since they're a poor design and are gone in YAML 1.2. + +Installation and usage +---------------------- + +The import path for the package is *gopkg.in/yaml.v3*. + +To install it, run: + + go get gopkg.in/yaml.v3 + +API documentation +----------------- + +If opened in a browser, the import path itself leads to the API documentation: + + - [https://gopkg.in/yaml.v3](https://gopkg.in/yaml.v3) + +API stability +------------- + +The package API for yaml v3 will remain stable as described in [gopkg.in](https://gopkg.in). + + +License +------- + +The yaml package is licensed under the MIT and Apache License 2.0 licenses. +Please see the LICENSE file for details. + + +Example +------- + +```Go +package main + +import ( + "fmt" + "log" + + "gopkg.in/yaml.v3" +) + +var data = ` +a: Easy! +b: + c: 2 + d: [3, 4] +` + +// Note: struct fields must be public in order for unmarshal to +// correctly populate the data. +type T struct { + A string + B struct { + RenamedC int `yaml:"c"` + D []int `yaml:",flow"` + } +} + +func main() { + t := T{} + + err := yaml.Unmarshal([]byte(data), &t) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- t:\n%v\n\n", t) + + d, err := yaml.Marshal(&t) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- t dump:\n%s\n\n", string(d)) + + m := make(map[interface{}]interface{}) + + err = yaml.Unmarshal([]byte(data), &m) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- m:\n%v\n\n", m) + + d, err = yaml.Marshal(&m) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- m dump:\n%s\n\n", string(d)) +} +``` + +This example will generate the following output: + +``` +--- t: +{Easy! {2 [3 4]}} + +--- t dump: +a: Easy! +b: + c: 2 + d: [3, 4] + + +--- m: +map[a:Easy! b:map[c:2 d:[3 4]]] + +--- m dump: +a: Easy! +b: + c: 2 + d: + - 3 + - 4 +``` + diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/apic.go b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/apic.go new file mode 100644 index 000000000..ae7d049f1 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/apic.go @@ -0,0 +1,747 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// Copyright (c) 2006-2010 Kirill Simonov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package yaml + +import ( + "io" +) + +func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) { + //fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens)) + + // Check if we can move the queue at the beginning of the buffer. + if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) { + if parser.tokens_head != len(parser.tokens) { + copy(parser.tokens, parser.tokens[parser.tokens_head:]) + } + parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head] + parser.tokens_head = 0 + } + parser.tokens = append(parser.tokens, *token) + if pos < 0 { + return + } + copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:]) + parser.tokens[parser.tokens_head+pos] = *token +} + +// Create a new parser object. +func yaml_parser_initialize(parser *yaml_parser_t) bool { + *parser = yaml_parser_t{ + raw_buffer: make([]byte, 0, input_raw_buffer_size), + buffer: make([]byte, 0, input_buffer_size), + } + return true +} + +// Destroy a parser object. +func yaml_parser_delete(parser *yaml_parser_t) { + *parser = yaml_parser_t{} +} + +// String read handler. +func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { + if parser.input_pos == len(parser.input) { + return 0, io.EOF + } + n = copy(buffer, parser.input[parser.input_pos:]) + parser.input_pos += n + return n, nil +} + +// Reader read handler. +func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { + return parser.input_reader.Read(buffer) +} + +// Set a string input. +func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) { + if parser.read_handler != nil { + panic("must set the input source only once") + } + parser.read_handler = yaml_string_read_handler + parser.input = input + parser.input_pos = 0 +} + +// Set a file input. +func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) { + if parser.read_handler != nil { + panic("must set the input source only once") + } + parser.read_handler = yaml_reader_read_handler + parser.input_reader = r +} + +// Set the source encoding. +func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) { + if parser.encoding != yaml_ANY_ENCODING { + panic("must set the encoding only once") + } + parser.encoding = encoding +} + +// Create a new emitter object. +func yaml_emitter_initialize(emitter *yaml_emitter_t) { + *emitter = yaml_emitter_t{ + buffer: make([]byte, output_buffer_size), + raw_buffer: make([]byte, 0, output_raw_buffer_size), + states: make([]yaml_emitter_state_t, 0, initial_stack_size), + events: make([]yaml_event_t, 0, initial_queue_size), + best_width: -1, + } +} + +// Destroy an emitter object. +func yaml_emitter_delete(emitter *yaml_emitter_t) { + *emitter = yaml_emitter_t{} +} + +// String write handler. +func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error { + *emitter.output_buffer = append(*emitter.output_buffer, buffer...) + return nil +} + +// yaml_writer_write_handler uses emitter.output_writer to write the +// emitted text. +func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error { + _, err := emitter.output_writer.Write(buffer) + return err +} + +// Set a string output. +func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) { + if emitter.write_handler != nil { + panic("must set the output target only once") + } + emitter.write_handler = yaml_string_write_handler + emitter.output_buffer = output_buffer +} + +// Set a file output. +func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) { + if emitter.write_handler != nil { + panic("must set the output target only once") + } + emitter.write_handler = yaml_writer_write_handler + emitter.output_writer = w +} + +// Set the output encoding. +func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) { + if emitter.encoding != yaml_ANY_ENCODING { + panic("must set the output encoding only once") + } + emitter.encoding = encoding +} + +// Set the canonical output style. +func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) { + emitter.canonical = canonical +} + +// Set the indentation increment. +func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) { + if indent < 2 || indent > 9 { + indent = 2 + } + emitter.best_indent = indent +} + +// Set the preferred line width. +func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) { + if width < 0 { + width = -1 + } + emitter.best_width = width +} + +// Set if unescaped non-ASCII characters are allowed. +func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) { + emitter.unicode = unicode +} + +// Set the preferred line break character. +func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) { + emitter.line_break = line_break +} + +///* +// * Destroy a token object. +// */ +// +//YAML_DECLARE(void) +//yaml_token_delete(yaml_token_t *token) +//{ +// assert(token); // Non-NULL token object expected. +// +// switch (token.type) +// { +// case YAML_TAG_DIRECTIVE_TOKEN: +// yaml_free(token.data.tag_directive.handle); +// yaml_free(token.data.tag_directive.prefix); +// break; +// +// case YAML_ALIAS_TOKEN: +// yaml_free(token.data.alias.value); +// break; +// +// case YAML_ANCHOR_TOKEN: +// yaml_free(token.data.anchor.value); +// break; +// +// case YAML_TAG_TOKEN: +// yaml_free(token.data.tag.handle); +// yaml_free(token.data.tag.suffix); +// break; +// +// case YAML_SCALAR_TOKEN: +// yaml_free(token.data.scalar.value); +// break; +// +// default: +// break; +// } +// +// memset(token, 0, sizeof(yaml_token_t)); +//} +// +///* +// * Check if a string is a valid UTF-8 sequence. +// * +// * Check 'reader.c' for more details on UTF-8 encoding. +// */ +// +//static int +//yaml_check_utf8(yaml_char_t *start, size_t length) +//{ +// yaml_char_t *end = start+length; +// yaml_char_t *pointer = start; +// +// while (pointer < end) { +// unsigned char octet; +// unsigned int width; +// unsigned int value; +// size_t k; +// +// octet = pointer[0]; +// width = (octet & 0x80) == 0x00 ? 1 : +// (octet & 0xE0) == 0xC0 ? 2 : +// (octet & 0xF0) == 0xE0 ? 3 : +// (octet & 0xF8) == 0xF0 ? 4 : 0; +// value = (octet & 0x80) == 0x00 ? octet & 0x7F : +// (octet & 0xE0) == 0xC0 ? octet & 0x1F : +// (octet & 0xF0) == 0xE0 ? octet & 0x0F : +// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; +// if (!width) return 0; +// if (pointer+width > end) return 0; +// for (k = 1; k < width; k ++) { +// octet = pointer[k]; +// if ((octet & 0xC0) != 0x80) return 0; +// value = (value << 6) + (octet & 0x3F); +// } +// if (!((width == 1) || +// (width == 2 && value >= 0x80) || +// (width == 3 && value >= 0x800) || +// (width == 4 && value >= 0x10000))) return 0; +// +// pointer += width; +// } +// +// return 1; +//} +// + +// Create STREAM-START. +func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) { + *event = yaml_event_t{ + typ: yaml_STREAM_START_EVENT, + encoding: encoding, + } +} + +// Create STREAM-END. +func yaml_stream_end_event_initialize(event *yaml_event_t) { + *event = yaml_event_t{ + typ: yaml_STREAM_END_EVENT, + } +} + +// Create DOCUMENT-START. +func yaml_document_start_event_initialize( + event *yaml_event_t, + version_directive *yaml_version_directive_t, + tag_directives []yaml_tag_directive_t, + implicit bool, +) { + *event = yaml_event_t{ + typ: yaml_DOCUMENT_START_EVENT, + version_directive: version_directive, + tag_directives: tag_directives, + implicit: implicit, + } +} + +// Create DOCUMENT-END. +func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) { + *event = yaml_event_t{ + typ: yaml_DOCUMENT_END_EVENT, + implicit: implicit, + } +} + +// Create ALIAS. +func yaml_alias_event_initialize(event *yaml_event_t, anchor []byte) bool { + *event = yaml_event_t{ + typ: yaml_ALIAS_EVENT, + anchor: anchor, + } + return true +} + +// Create SCALAR. +func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool { + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + anchor: anchor, + tag: tag, + value: value, + implicit: plain_implicit, + quoted_implicit: quoted_implicit, + style: yaml_style_t(style), + } + return true +} + +// Create SEQUENCE-START. +func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool { + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(style), + } + return true +} + +// Create SEQUENCE-END. +func yaml_sequence_end_event_initialize(event *yaml_event_t) bool { + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + } + return true +} + +// Create MAPPING-START. +func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) { + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(style), + } +} + +// Create MAPPING-END. +func yaml_mapping_end_event_initialize(event *yaml_event_t) { + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + } +} + +// Destroy an event object. +func yaml_event_delete(event *yaml_event_t) { + *event = yaml_event_t{} +} + +///* +// * Create a document object. +// */ +// +//YAML_DECLARE(int) +//yaml_document_initialize(document *yaml_document_t, +// version_directive *yaml_version_directive_t, +// tag_directives_start *yaml_tag_directive_t, +// tag_directives_end *yaml_tag_directive_t, +// start_implicit int, end_implicit int) +//{ +// struct { +// error yaml_error_type_t +// } context +// struct { +// start *yaml_node_t +// end *yaml_node_t +// top *yaml_node_t +// } nodes = { NULL, NULL, NULL } +// version_directive_copy *yaml_version_directive_t = NULL +// struct { +// start *yaml_tag_directive_t +// end *yaml_tag_directive_t +// top *yaml_tag_directive_t +// } tag_directives_copy = { NULL, NULL, NULL } +// value yaml_tag_directive_t = { NULL, NULL } +// mark yaml_mark_t = { 0, 0, 0 } +// +// assert(document) // Non-NULL document object is expected. +// assert((tag_directives_start && tag_directives_end) || +// (tag_directives_start == tag_directives_end)) +// // Valid tag directives are expected. +// +// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error +// +// if (version_directive) { +// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t)) +// if (!version_directive_copy) goto error +// version_directive_copy.major = version_directive.major +// version_directive_copy.minor = version_directive.minor +// } +// +// if (tag_directives_start != tag_directives_end) { +// tag_directive *yaml_tag_directive_t +// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE)) +// goto error +// for (tag_directive = tag_directives_start +// tag_directive != tag_directives_end; tag_directive ++) { +// assert(tag_directive.handle) +// assert(tag_directive.prefix) +// if (!yaml_check_utf8(tag_directive.handle, +// strlen((char *)tag_directive.handle))) +// goto error +// if (!yaml_check_utf8(tag_directive.prefix, +// strlen((char *)tag_directive.prefix))) +// goto error +// value.handle = yaml_strdup(tag_directive.handle) +// value.prefix = yaml_strdup(tag_directive.prefix) +// if (!value.handle || !value.prefix) goto error +// if (!PUSH(&context, tag_directives_copy, value)) +// goto error +// value.handle = NULL +// value.prefix = NULL +// } +// } +// +// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy, +// tag_directives_copy.start, tag_directives_copy.top, +// start_implicit, end_implicit, mark, mark) +// +// return 1 +// +//error: +// STACK_DEL(&context, nodes) +// yaml_free(version_directive_copy) +// while (!STACK_EMPTY(&context, tag_directives_copy)) { +// value yaml_tag_directive_t = POP(&context, tag_directives_copy) +// yaml_free(value.handle) +// yaml_free(value.prefix) +// } +// STACK_DEL(&context, tag_directives_copy) +// yaml_free(value.handle) +// yaml_free(value.prefix) +// +// return 0 +//} +// +///* +// * Destroy a document object. +// */ +// +//YAML_DECLARE(void) +//yaml_document_delete(document *yaml_document_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// tag_directive *yaml_tag_directive_t +// +// context.error = YAML_NO_ERROR // Eliminate a compiler warning. +// +// assert(document) // Non-NULL document object is expected. +// +// while (!STACK_EMPTY(&context, document.nodes)) { +// node yaml_node_t = POP(&context, document.nodes) +// yaml_free(node.tag) +// switch (node.type) { +// case YAML_SCALAR_NODE: +// yaml_free(node.data.scalar.value) +// break +// case YAML_SEQUENCE_NODE: +// STACK_DEL(&context, node.data.sequence.items) +// break +// case YAML_MAPPING_NODE: +// STACK_DEL(&context, node.data.mapping.pairs) +// break +// default: +// assert(0) // Should not happen. +// } +// } +// STACK_DEL(&context, document.nodes) +// +// yaml_free(document.version_directive) +// for (tag_directive = document.tag_directives.start +// tag_directive != document.tag_directives.end +// tag_directive++) { +// yaml_free(tag_directive.handle) +// yaml_free(tag_directive.prefix) +// } +// yaml_free(document.tag_directives.start) +// +// memset(document, 0, sizeof(yaml_document_t)) +//} +// +///** +// * Get a document node. +// */ +// +//YAML_DECLARE(yaml_node_t *) +//yaml_document_get_node(document *yaml_document_t, index int) +//{ +// assert(document) // Non-NULL document object is expected. +// +// if (index > 0 && document.nodes.start + index <= document.nodes.top) { +// return document.nodes.start + index - 1 +// } +// return NULL +//} +// +///** +// * Get the root object. +// */ +// +//YAML_DECLARE(yaml_node_t *) +//yaml_document_get_root_node(document *yaml_document_t) +//{ +// assert(document) // Non-NULL document object is expected. +// +// if (document.nodes.top != document.nodes.start) { +// return document.nodes.start +// } +// return NULL +//} +// +///* +// * Add a scalar node to a document. +// */ +// +//YAML_DECLARE(int) +//yaml_document_add_scalar(document *yaml_document_t, +// tag *yaml_char_t, value *yaml_char_t, length int, +// style yaml_scalar_style_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// mark yaml_mark_t = { 0, 0, 0 } +// tag_copy *yaml_char_t = NULL +// value_copy *yaml_char_t = NULL +// node yaml_node_t +// +// assert(document) // Non-NULL document object is expected. +// assert(value) // Non-NULL value is expected. +// +// if (!tag) { +// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG +// } +// +// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error +// tag_copy = yaml_strdup(tag) +// if (!tag_copy) goto error +// +// if (length < 0) { +// length = strlen((char *)value) +// } +// +// if (!yaml_check_utf8(value, length)) goto error +// value_copy = yaml_malloc(length+1) +// if (!value_copy) goto error +// memcpy(value_copy, value, length) +// value_copy[length] = '\0' +// +// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark) +// if (!PUSH(&context, document.nodes, node)) goto error +// +// return document.nodes.top - document.nodes.start +// +//error: +// yaml_free(tag_copy) +// yaml_free(value_copy) +// +// return 0 +//} +// +///* +// * Add a sequence node to a document. +// */ +// +//YAML_DECLARE(int) +//yaml_document_add_sequence(document *yaml_document_t, +// tag *yaml_char_t, style yaml_sequence_style_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// mark yaml_mark_t = { 0, 0, 0 } +// tag_copy *yaml_char_t = NULL +// struct { +// start *yaml_node_item_t +// end *yaml_node_item_t +// top *yaml_node_item_t +// } items = { NULL, NULL, NULL } +// node yaml_node_t +// +// assert(document) // Non-NULL document object is expected. +// +// if (!tag) { +// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG +// } +// +// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error +// tag_copy = yaml_strdup(tag) +// if (!tag_copy) goto error +// +// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error +// +// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end, +// style, mark, mark) +// if (!PUSH(&context, document.nodes, node)) goto error +// +// return document.nodes.top - document.nodes.start +// +//error: +// STACK_DEL(&context, items) +// yaml_free(tag_copy) +// +// return 0 +//} +// +///* +// * Add a mapping node to a document. +// */ +// +//YAML_DECLARE(int) +//yaml_document_add_mapping(document *yaml_document_t, +// tag *yaml_char_t, style yaml_mapping_style_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// mark yaml_mark_t = { 0, 0, 0 } +// tag_copy *yaml_char_t = NULL +// struct { +// start *yaml_node_pair_t +// end *yaml_node_pair_t +// top *yaml_node_pair_t +// } pairs = { NULL, NULL, NULL } +// node yaml_node_t +// +// assert(document) // Non-NULL document object is expected. +// +// if (!tag) { +// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG +// } +// +// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error +// tag_copy = yaml_strdup(tag) +// if (!tag_copy) goto error +// +// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error +// +// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end, +// style, mark, mark) +// if (!PUSH(&context, document.nodes, node)) goto error +// +// return document.nodes.top - document.nodes.start +// +//error: +// STACK_DEL(&context, pairs) +// yaml_free(tag_copy) +// +// return 0 +//} +// +///* +// * Append an item to a sequence node. +// */ +// +//YAML_DECLARE(int) +//yaml_document_append_sequence_item(document *yaml_document_t, +// sequence int, item int) +//{ +// struct { +// error yaml_error_type_t +// } context +// +// assert(document) // Non-NULL document is required. +// assert(sequence > 0 +// && document.nodes.start + sequence <= document.nodes.top) +// // Valid sequence id is required. +// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE) +// // A sequence node is required. +// assert(item > 0 && document.nodes.start + item <= document.nodes.top) +// // Valid item id is required. +// +// if (!PUSH(&context, +// document.nodes.start[sequence-1].data.sequence.items, item)) +// return 0 +// +// return 1 +//} +// +///* +// * Append a pair of a key and a value to a mapping node. +// */ +// +//YAML_DECLARE(int) +//yaml_document_append_mapping_pair(document *yaml_document_t, +// mapping int, key int, value int) +//{ +// struct { +// error yaml_error_type_t +// } context +// +// pair yaml_node_pair_t +// +// assert(document) // Non-NULL document is required. +// assert(mapping > 0 +// && document.nodes.start + mapping <= document.nodes.top) +// // Valid mapping id is required. +// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE) +// // A mapping node is required. +// assert(key > 0 && document.nodes.start + key <= document.nodes.top) +// // Valid key id is required. +// assert(value > 0 && document.nodes.start + value <= document.nodes.top) +// // Valid value id is required. +// +// pair.key = key +// pair.value = value +// +// if (!PUSH(&context, +// document.nodes.start[mapping-1].data.mapping.pairs, pair)) +// return 0 +// +// return 1 +//} +// +// diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/decode.go b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/decode.go new file mode 100644 index 000000000..df36e3a30 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/decode.go @@ -0,0 +1,950 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package yaml + +import ( + "encoding" + "encoding/base64" + "fmt" + "io" + "math" + "reflect" + "strconv" + "time" +) + +// ---------------------------------------------------------------------------- +// Parser, produces a node tree out of a libyaml event stream. + +type parser struct { + parser yaml_parser_t + event yaml_event_t + doc *Node + anchors map[string]*Node + doneInit bool + textless bool +} + +func newParser(b []byte) *parser { + p := parser{} + if !yaml_parser_initialize(&p.parser) { + panic("failed to initialize YAML emitter") + } + if len(b) == 0 { + b = []byte{'\n'} + } + yaml_parser_set_input_string(&p.parser, b) + return &p +} + +func newParserFromReader(r io.Reader) *parser { + p := parser{} + if !yaml_parser_initialize(&p.parser) { + panic("failed to initialize YAML emitter") + } + yaml_parser_set_input_reader(&p.parser, r) + return &p +} + +func (p *parser) init() { + if p.doneInit { + return + } + p.anchors = make(map[string]*Node) + p.expect(yaml_STREAM_START_EVENT) + p.doneInit = true +} + +func (p *parser) destroy() { + if p.event.typ != yaml_NO_EVENT { + yaml_event_delete(&p.event) + } + yaml_parser_delete(&p.parser) +} + +// expect consumes an event from the event stream and +// checks that it's of the expected type. +func (p *parser) expect(e yaml_event_type_t) { + if p.event.typ == yaml_NO_EVENT { + if !yaml_parser_parse(&p.parser, &p.event) { + p.fail() + } + } + if p.event.typ == yaml_STREAM_END_EVENT { + failf("attempted to go past the end of stream; corrupted value?") + } + if p.event.typ != e { + p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ) + p.fail() + } + yaml_event_delete(&p.event) + p.event.typ = yaml_NO_EVENT +} + +// peek peeks at the next event in the event stream, +// puts the results into p.event and returns the event type. +func (p *parser) peek() yaml_event_type_t { + if p.event.typ != yaml_NO_EVENT { + return p.event.typ + } + if !yaml_parser_parse(&p.parser, &p.event) { + p.fail() + } + return p.event.typ +} + +func (p *parser) fail() { + var where string + var line int + if p.parser.context_mark.line != 0 { + line = p.parser.context_mark.line + // Scanner errors don't iterate line before returning error + if p.parser.error == yaml_SCANNER_ERROR { + line++ + } + } else if p.parser.problem_mark.line != 0 { + line = p.parser.problem_mark.line + // Scanner errors don't iterate line before returning error + if p.parser.error == yaml_SCANNER_ERROR { + line++ + } + } + if line != 0 { + where = "line " + strconv.Itoa(line) + ": " + } + var msg string + if len(p.parser.problem) > 0 { + msg = p.parser.problem + } else { + msg = "unknown problem parsing YAML content" + } + failf("%s%s", where, msg) +} + +func (p *parser) anchor(n *Node, anchor []byte) { + if anchor != nil { + n.Anchor = string(anchor) + p.anchors[n.Anchor] = n + } +} + +func (p *parser) parse() *Node { + p.init() + switch p.peek() { + case yaml_SCALAR_EVENT: + return p.scalar() + case yaml_ALIAS_EVENT: + return p.alias() + case yaml_MAPPING_START_EVENT: + return p.mapping() + case yaml_SEQUENCE_START_EVENT: + return p.sequence() + case yaml_DOCUMENT_START_EVENT: + return p.document() + case yaml_STREAM_END_EVENT: + // Happens when attempting to decode an empty buffer. + return nil + case yaml_TAIL_COMMENT_EVENT: + panic("internal error: unexpected tail comment event (please report)") + default: + panic("internal error: attempted to parse unknown event (please report): " + p.event.typ.String()) + } +} + +func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node { + var style Style + if tag != "" && tag != "!" { + tag = shortTag(tag) + style = TaggedStyle + } else if defaultTag != "" { + tag = defaultTag + } else if kind == ScalarNode { + tag, _ = resolve("", value) + } + n := &Node{ + Kind: kind, + Tag: tag, + Value: value, + Style: style, + } + if !p.textless { + n.Line = p.event.start_mark.line + 1 + n.Column = p.event.start_mark.column + 1 + n.HeadComment = string(p.event.head_comment) + n.LineComment = string(p.event.line_comment) + n.FootComment = string(p.event.foot_comment) + } + return n +} + +func (p *parser) parseChild(parent *Node) *Node { + child := p.parse() + parent.Content = append(parent.Content, child) + return child +} + +func (p *parser) document() *Node { + n := p.node(DocumentNode, "", "", "") + p.doc = n + p.expect(yaml_DOCUMENT_START_EVENT) + p.parseChild(n) + if p.peek() == yaml_DOCUMENT_END_EVENT { + n.FootComment = string(p.event.foot_comment) + } + p.expect(yaml_DOCUMENT_END_EVENT) + return n +} + +func (p *parser) alias() *Node { + n := p.node(AliasNode, "", "", string(p.event.anchor)) + n.Alias = p.anchors[n.Value] + if n.Alias == nil { + failf("unknown anchor '%s' referenced", n.Value) + } + p.expect(yaml_ALIAS_EVENT) + return n +} + +func (p *parser) scalar() *Node { + var parsedStyle = p.event.scalar_style() + var nodeStyle Style + switch { + case parsedStyle&yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0: + nodeStyle = DoubleQuotedStyle + case parsedStyle&yaml_SINGLE_QUOTED_SCALAR_STYLE != 0: + nodeStyle = SingleQuotedStyle + case parsedStyle&yaml_LITERAL_SCALAR_STYLE != 0: + nodeStyle = LiteralStyle + case parsedStyle&yaml_FOLDED_SCALAR_STYLE != 0: + nodeStyle = FoldedStyle + } + var nodeValue = string(p.event.value) + var nodeTag = string(p.event.tag) + var defaultTag string + if nodeStyle == 0 { + if nodeValue == "<<" { + defaultTag = mergeTag + } + } else { + defaultTag = strTag + } + n := p.node(ScalarNode, defaultTag, nodeTag, nodeValue) + n.Style |= nodeStyle + p.anchor(n, p.event.anchor) + p.expect(yaml_SCALAR_EVENT) + return n +} + +func (p *parser) sequence() *Node { + n := p.node(SequenceNode, seqTag, string(p.event.tag), "") + if p.event.sequence_style()&yaml_FLOW_SEQUENCE_STYLE != 0 { + n.Style |= FlowStyle + } + p.anchor(n, p.event.anchor) + p.expect(yaml_SEQUENCE_START_EVENT) + for p.peek() != yaml_SEQUENCE_END_EVENT { + p.parseChild(n) + } + n.LineComment = string(p.event.line_comment) + n.FootComment = string(p.event.foot_comment) + p.expect(yaml_SEQUENCE_END_EVENT) + return n +} + +func (p *parser) mapping() *Node { + n := p.node(MappingNode, mapTag, string(p.event.tag), "") + block := true + if p.event.mapping_style()&yaml_FLOW_MAPPING_STYLE != 0 { + block = false + n.Style |= FlowStyle + } + p.anchor(n, p.event.anchor) + p.expect(yaml_MAPPING_START_EVENT) + for p.peek() != yaml_MAPPING_END_EVENT { + k := p.parseChild(n) + if block && k.FootComment != "" { + // Must be a foot comment for the prior value when being dedented. + if len(n.Content) > 2 { + n.Content[len(n.Content)-3].FootComment = k.FootComment + k.FootComment = "" + } + } + v := p.parseChild(n) + if k.FootComment == "" && v.FootComment != "" { + k.FootComment = v.FootComment + v.FootComment = "" + } + if p.peek() == yaml_TAIL_COMMENT_EVENT { + if k.FootComment == "" { + k.FootComment = string(p.event.foot_comment) + } + p.expect(yaml_TAIL_COMMENT_EVENT) + } + } + n.LineComment = string(p.event.line_comment) + n.FootComment = string(p.event.foot_comment) + if n.Style&FlowStyle == 0 && n.FootComment != "" && len(n.Content) > 1 { + n.Content[len(n.Content)-2].FootComment = n.FootComment + n.FootComment = "" + } + p.expect(yaml_MAPPING_END_EVENT) + return n +} + +// ---------------------------------------------------------------------------- +// Decoder, unmarshals a node into a provided value. + +type decoder struct { + doc *Node + aliases map[*Node]bool + terrors []string + + stringMapType reflect.Type + generalMapType reflect.Type + + knownFields bool + uniqueKeys bool + decodeCount int + aliasCount int + aliasDepth int +} + +var ( + nodeType = reflect.TypeOf(Node{}) + durationType = reflect.TypeOf(time.Duration(0)) + stringMapType = reflect.TypeOf(map[string]interface{}{}) + generalMapType = reflect.TypeOf(map[interface{}]interface{}{}) + ifaceType = generalMapType.Elem() + timeType = reflect.TypeOf(time.Time{}) + ptrTimeType = reflect.TypeOf(&time.Time{}) +) + +func newDecoder() *decoder { + d := &decoder{ + stringMapType: stringMapType, + generalMapType: generalMapType, + uniqueKeys: true, + } + d.aliases = make(map[*Node]bool) + return d +} + +func (d *decoder) terror(n *Node, tag string, out reflect.Value) { + if n.Tag != "" { + tag = n.Tag + } + value := n.Value + if tag != seqTag && tag != mapTag { + if len(value) > 10 { + value = " `" + value[:7] + "...`" + } else { + value = " `" + value + "`" + } + } + d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.Line, shortTag(tag), value, out.Type())) +} + +func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) { + err := u.UnmarshalYAML(n) + if e, ok := err.(*TypeError); ok { + d.terrors = append(d.terrors, e.Errors...) + return false + } + if err != nil { + fail(err) + } + return true +} + +func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good bool) { + terrlen := len(d.terrors) + err := u.UnmarshalYAML(func(v interface{}) (err error) { + defer handleErr(&err) + d.unmarshal(n, reflect.ValueOf(v)) + if len(d.terrors) > terrlen { + issues := d.terrors[terrlen:] + d.terrors = d.terrors[:terrlen] + return &TypeError{issues} + } + return nil + }) + if e, ok := err.(*TypeError); ok { + d.terrors = append(d.terrors, e.Errors...) + return false + } + if err != nil { + fail(err) + } + return true +} + +// d.prepare initializes and dereferences pointers and calls UnmarshalYAML +// if a value is found to implement it. +// It returns the initialized and dereferenced out value, whether +// unmarshalling was already done by UnmarshalYAML, and if so whether +// its types unmarshalled appropriately. +// +// If n holds a null value, prepare returns before doing anything. +func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) { + if n.ShortTag() == nullTag { + return out, false, false + } + again := true + for again { + again = false + if out.Kind() == reflect.Ptr { + if out.IsNil() { + out.Set(reflect.New(out.Type().Elem())) + } + out = out.Elem() + again = true + } + if out.CanAddr() { + outi := out.Addr().Interface() + if u, ok := outi.(Unmarshaler); ok { + good = d.callUnmarshaler(n, u) + return out, true, good + } + if u, ok := outi.(obsoleteUnmarshaler); ok { + good = d.callObsoleteUnmarshaler(n, u) + return out, true, good + } + } + } + return out, false, false +} + +func (d *decoder) fieldByIndex(n *Node, v reflect.Value, index []int) (field reflect.Value) { + if n.ShortTag() == nullTag { + return reflect.Value{} + } + for _, num := range index { + for { + if v.Kind() == reflect.Ptr { + if v.IsNil() { + v.Set(reflect.New(v.Type().Elem())) + } + v = v.Elem() + continue + } + break + } + v = v.Field(num) + } + return v +} + +const ( + // 400,000 decode operations is ~500kb of dense object declarations, or + // ~5kb of dense object declarations with 10000% alias expansion + alias_ratio_range_low = 400000 + + // 4,000,000 decode operations is ~5MB of dense object declarations, or + // ~4.5MB of dense object declarations with 10% alias expansion + alias_ratio_range_high = 4000000 + + // alias_ratio_range is the range over which we scale allowed alias ratios + alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low) +) + +func allowedAliasRatio(decodeCount int) float64 { + switch { + case decodeCount <= alias_ratio_range_low: + // allow 99% to come from alias expansion for small-to-medium documents + return 0.99 + case decodeCount >= alias_ratio_range_high: + // allow 10% to come from alias expansion for very large documents + return 0.10 + default: + // scale smoothly from 99% down to 10% over the range. + // this maps to 396,000 - 400,000 allowed alias-driven decodes over the range. + // 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps). + return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range) + } +} + +func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) { + d.decodeCount++ + if d.aliasDepth > 0 { + d.aliasCount++ + } + if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) { + failf("document contains excessive aliasing") + } + if out.Type() == nodeType { + out.Set(reflect.ValueOf(n).Elem()) + return true + } + switch n.Kind { + case DocumentNode: + return d.document(n, out) + case AliasNode: + return d.alias(n, out) + } + out, unmarshaled, good := d.prepare(n, out) + if unmarshaled { + return good + } + switch n.Kind { + case ScalarNode: + good = d.scalar(n, out) + case MappingNode: + good = d.mapping(n, out) + case SequenceNode: + good = d.sequence(n, out) + case 0: + if n.IsZero() { + return d.null(out) + } + fallthrough + default: + failf("cannot decode node with unknown kind %d", n.Kind) + } + return good +} + +func (d *decoder) document(n *Node, out reflect.Value) (good bool) { + if len(n.Content) == 1 { + d.doc = n + d.unmarshal(n.Content[0], out) + return true + } + return false +} + +func (d *decoder) alias(n *Node, out reflect.Value) (good bool) { + if d.aliases[n] { + // TODO this could actually be allowed in some circumstances. + failf("anchor '%s' value contains itself", n.Value) + } + d.aliases[n] = true + d.aliasDepth++ + good = d.unmarshal(n.Alias, out) + d.aliasDepth-- + delete(d.aliases, n) + return good +} + +var zeroValue reflect.Value + +func resetMap(out reflect.Value) { + for _, k := range out.MapKeys() { + out.SetMapIndex(k, zeroValue) + } +} + +func (d *decoder) null(out reflect.Value) bool { + if out.CanAddr() { + switch out.Kind() { + case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: + out.Set(reflect.Zero(out.Type())) + return true + } + } + return false +} + +func (d *decoder) scalar(n *Node, out reflect.Value) bool { + var tag string + var resolved interface{} + if n.indicatedString() { + tag = strTag + resolved = n.Value + } else { + tag, resolved = resolve(n.Tag, n.Value) + if tag == binaryTag { + data, err := base64.StdEncoding.DecodeString(resolved.(string)) + if err != nil { + failf("!!binary value contains invalid base64 data") + } + resolved = string(data) + } + } + if resolved == nil { + return d.null(out) + } + if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { + // We've resolved to exactly the type we want, so use that. + out.Set(resolvedv) + return true + } + // Perhaps we can use the value as a TextUnmarshaler to + // set its value. + if out.CanAddr() { + u, ok := out.Addr().Interface().(encoding.TextUnmarshaler) + if ok { + var text []byte + if tag == binaryTag { + text = []byte(resolved.(string)) + } else { + // We let any value be unmarshaled into TextUnmarshaler. + // That might be more lax than we'd like, but the + // TextUnmarshaler itself should bowl out any dubious values. + text = []byte(n.Value) + } + err := u.UnmarshalText(text) + if err != nil { + fail(err) + } + return true + } + } + switch out.Kind() { + case reflect.String: + if tag == binaryTag { + out.SetString(resolved.(string)) + return true + } + out.SetString(n.Value) + return true + case reflect.Interface: + out.Set(reflect.ValueOf(resolved)) + return true + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + // This used to work in v2, but it's very unfriendly. + isDuration := out.Type() == durationType + + switch resolved := resolved.(type) { + case int: + if !isDuration && !out.OverflowInt(int64(resolved)) { + out.SetInt(int64(resolved)) + return true + } + case int64: + if !isDuration && !out.OverflowInt(resolved) { + out.SetInt(resolved) + return true + } + case uint64: + if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { + out.SetInt(int64(resolved)) + return true + } + case float64: + if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { + out.SetInt(int64(resolved)) + return true + } + case string: + if out.Type() == durationType { + d, err := time.ParseDuration(resolved) + if err == nil { + out.SetInt(int64(d)) + return true + } + } + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + switch resolved := resolved.(type) { + case int: + if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + return true + } + case int64: + if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + return true + } + case uint64: + if !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + return true + } + case float64: + if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + return true + } + } + case reflect.Bool: + switch resolved := resolved.(type) { + case bool: + out.SetBool(resolved) + return true + case string: + // This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html). + // It only works if explicitly attempting to unmarshal into a typed bool value. + switch resolved { + case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON": + out.SetBool(true) + return true + case "n", "N", "no", "No", "NO", "off", "Off", "OFF": + out.SetBool(false) + return true + } + } + case reflect.Float32, reflect.Float64: + switch resolved := resolved.(type) { + case int: + out.SetFloat(float64(resolved)) + return true + case int64: + out.SetFloat(float64(resolved)) + return true + case uint64: + out.SetFloat(float64(resolved)) + return true + case float64: + out.SetFloat(resolved) + return true + } + case reflect.Struct: + if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { + out.Set(resolvedv) + return true + } + case reflect.Ptr: + panic("yaml internal error: please report the issue") + } + d.terror(n, tag, out) + return false +} + +func settableValueOf(i interface{}) reflect.Value { + v := reflect.ValueOf(i) + sv := reflect.New(v.Type()).Elem() + sv.Set(v) + return sv +} + +func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) { + l := len(n.Content) + + var iface reflect.Value + switch out.Kind() { + case reflect.Slice: + out.Set(reflect.MakeSlice(out.Type(), l, l)) + case reflect.Array: + if l != out.Len() { + failf("invalid array: want %d elements but got %d", out.Len(), l) + } + case reflect.Interface: + // No type hints. Will have to use a generic sequence. + iface = out + out = settableValueOf(make([]interface{}, l)) + default: + d.terror(n, seqTag, out) + return false + } + et := out.Type().Elem() + + j := 0 + for i := 0; i < l; i++ { + e := reflect.New(et).Elem() + if ok := d.unmarshal(n.Content[i], e); ok { + out.Index(j).Set(e) + j++ + } + } + if out.Kind() != reflect.Array { + out.Set(out.Slice(0, j)) + } + if iface.IsValid() { + iface.Set(out) + } + return true +} + +func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) { + l := len(n.Content) + if d.uniqueKeys { + nerrs := len(d.terrors) + for i := 0; i < l; i += 2 { + ni := n.Content[i] + for j := i + 2; j < l; j += 2 { + nj := n.Content[j] + if ni.Kind == nj.Kind && ni.Value == nj.Value { + d.terrors = append(d.terrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", nj.Line, nj.Value, ni.Line)) + } + } + } + if len(d.terrors) > nerrs { + return false + } + } + switch out.Kind() { + case reflect.Struct: + return d.mappingStruct(n, out) + case reflect.Map: + // okay + case reflect.Interface: + iface := out + if isStringMap(n) { + out = reflect.MakeMap(d.stringMapType) + } else { + out = reflect.MakeMap(d.generalMapType) + } + iface.Set(out) + default: + d.terror(n, mapTag, out) + return false + } + + outt := out.Type() + kt := outt.Key() + et := outt.Elem() + + stringMapType := d.stringMapType + generalMapType := d.generalMapType + if outt.Elem() == ifaceType { + if outt.Key().Kind() == reflect.String { + d.stringMapType = outt + } else if outt.Key() == ifaceType { + d.generalMapType = outt + } + } + + mapIsNew := false + if out.IsNil() { + out.Set(reflect.MakeMap(outt)) + mapIsNew = true + } + for i := 0; i < l; i += 2 { + if isMerge(n.Content[i]) { + d.merge(n.Content[i+1], out) + continue + } + k := reflect.New(kt).Elem() + if d.unmarshal(n.Content[i], k) { + kkind := k.Kind() + if kkind == reflect.Interface { + kkind = k.Elem().Kind() + } + if kkind == reflect.Map || kkind == reflect.Slice { + failf("invalid map key: %#v", k.Interface()) + } + e := reflect.New(et).Elem() + if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) { + out.SetMapIndex(k, e) + } + } + } + d.stringMapType = stringMapType + d.generalMapType = generalMapType + return true +} + +func isStringMap(n *Node) bool { + if n.Kind != MappingNode { + return false + } + l := len(n.Content) + for i := 0; i < l; i += 2 { + if n.Content[i].ShortTag() != strTag { + return false + } + } + return true +} + +func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) { + sinfo, err := getStructInfo(out.Type()) + if err != nil { + panic(err) + } + + var inlineMap reflect.Value + var elemType reflect.Type + if sinfo.InlineMap != -1 { + inlineMap = out.Field(sinfo.InlineMap) + inlineMap.Set(reflect.New(inlineMap.Type()).Elem()) + elemType = inlineMap.Type().Elem() + } + + for _, index := range sinfo.InlineUnmarshalers { + field := d.fieldByIndex(n, out, index) + d.prepare(n, field) + } + + var doneFields []bool + if d.uniqueKeys { + doneFields = make([]bool, len(sinfo.FieldsList)) + } + name := settableValueOf("") + l := len(n.Content) + for i := 0; i < l; i += 2 { + ni := n.Content[i] + if isMerge(ni) { + d.merge(n.Content[i+1], out) + continue + } + if !d.unmarshal(ni, name) { + continue + } + if info, ok := sinfo.FieldsMap[name.String()]; ok { + if d.uniqueKeys { + if doneFields[info.Id] { + d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type())) + continue + } + doneFields[info.Id] = true + } + var field reflect.Value + if info.Inline == nil { + field = out.Field(info.Num) + } else { + field = d.fieldByIndex(n, out, info.Inline) + } + d.unmarshal(n.Content[i+1], field) + } else if sinfo.InlineMap != -1 { + if inlineMap.IsNil() { + inlineMap.Set(reflect.MakeMap(inlineMap.Type())) + } + value := reflect.New(elemType).Elem() + d.unmarshal(n.Content[i+1], value) + inlineMap.SetMapIndex(name, value) + } else if d.knownFields { + d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type())) + } + } + return true +} + +func failWantMap() { + failf("map merge requires map or sequence of maps as the value") +} + +func (d *decoder) merge(n *Node, out reflect.Value) { + switch n.Kind { + case MappingNode: + d.unmarshal(n, out) + case AliasNode: + if n.Alias != nil && n.Alias.Kind != MappingNode { + failWantMap() + } + d.unmarshal(n, out) + case SequenceNode: + // Step backwards as earlier nodes take precedence. + for i := len(n.Content) - 1; i >= 0; i-- { + ni := n.Content[i] + if ni.Kind == AliasNode { + if ni.Alias != nil && ni.Alias.Kind != MappingNode { + failWantMap() + } + } else if ni.Kind != MappingNode { + failWantMap() + } + d.unmarshal(ni, out) + } + default: + failWantMap() + } +} + +func isMerge(n *Node) bool { + return n.Kind == ScalarNode && n.Value == "<<" && (n.Tag == "" || n.Tag == "!" || shortTag(n.Tag) == mergeTag) +} diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/emitterc.go b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/emitterc.go new file mode 100644 index 000000000..f0f3d1867 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/emitterc.go @@ -0,0 +1,2028 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// Copyright (c) 2006-2010 Kirill Simonov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package yaml + +import ( + "bytes" + "fmt" +) + +// Flush the buffer if needed. +func flush(emitter *yaml_emitter_t) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) { + return yaml_emitter_flush(emitter) + } + return true +} + +// Put a character to the output buffer. +func put(emitter *yaml_emitter_t, value byte) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { + return false + } + emitter.buffer[emitter.buffer_pos] = value + emitter.buffer_pos++ + emitter.column++ + return true +} + +// Put a line break to the output buffer. +func put_break(emitter *yaml_emitter_t) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { + return false + } + switch emitter.line_break { + case yaml_CR_BREAK: + emitter.buffer[emitter.buffer_pos] = '\r' + emitter.buffer_pos += 1 + case yaml_LN_BREAK: + emitter.buffer[emitter.buffer_pos] = '\n' + emitter.buffer_pos += 1 + case yaml_CRLN_BREAK: + emitter.buffer[emitter.buffer_pos+0] = '\r' + emitter.buffer[emitter.buffer_pos+1] = '\n' + emitter.buffer_pos += 2 + default: + panic("unknown line break setting") + } + if emitter.column == 0 { + emitter.space_above = true + } + emitter.column = 0 + emitter.line++ + // [Go] Do this here and below and drop from everywhere else (see commented lines). + emitter.indention = true + return true +} + +// Copy a character from a string into buffer. +func write(emitter *yaml_emitter_t, s []byte, i *int) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { + return false + } + p := emitter.buffer_pos + w := width(s[*i]) + switch w { + case 4: + emitter.buffer[p+3] = s[*i+3] + fallthrough + case 3: + emitter.buffer[p+2] = s[*i+2] + fallthrough + case 2: + emitter.buffer[p+1] = s[*i+1] + fallthrough + case 1: + emitter.buffer[p+0] = s[*i+0] + default: + panic("unknown character width") + } + emitter.column++ + emitter.buffer_pos += w + *i += w + return true +} + +// Write a whole string into buffer. +func write_all(emitter *yaml_emitter_t, s []byte) bool { + for i := 0; i < len(s); { + if !write(emitter, s, &i) { + return false + } + } + return true +} + +// Copy a line break character from a string into buffer. +func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool { + if s[*i] == '\n' { + if !put_break(emitter) { + return false + } + *i++ + } else { + if !write(emitter, s, i) { + return false + } + if emitter.column == 0 { + emitter.space_above = true + } + emitter.column = 0 + emitter.line++ + // [Go] Do this here and above and drop from everywhere else (see commented lines). + emitter.indention = true + } + return true +} + +// Set an emitter error and return false. +func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool { + emitter.error = yaml_EMITTER_ERROR + emitter.problem = problem + return false +} + +// Emit an event. +func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool { + emitter.events = append(emitter.events, *event) + for !yaml_emitter_need_more_events(emitter) { + event := &emitter.events[emitter.events_head] + if !yaml_emitter_analyze_event(emitter, event) { + return false + } + if !yaml_emitter_state_machine(emitter, event) { + return false + } + yaml_event_delete(event) + emitter.events_head++ + } + return true +} + +// Check if we need to accumulate more events before emitting. +// +// We accumulate extra +// - 1 event for DOCUMENT-START +// - 2 events for SEQUENCE-START +// - 3 events for MAPPING-START +// +func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool { + if emitter.events_head == len(emitter.events) { + return true + } + var accumulate int + switch emitter.events[emitter.events_head].typ { + case yaml_DOCUMENT_START_EVENT: + accumulate = 1 + break + case yaml_SEQUENCE_START_EVENT: + accumulate = 2 + break + case yaml_MAPPING_START_EVENT: + accumulate = 3 + break + default: + return false + } + if len(emitter.events)-emitter.events_head > accumulate { + return false + } + var level int + for i := emitter.events_head; i < len(emitter.events); i++ { + switch emitter.events[i].typ { + case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT: + level++ + case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT: + level-- + } + if level == 0 { + return false + } + } + return true +} + +// Append a directive to the directives stack. +func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool { + for i := 0; i < len(emitter.tag_directives); i++ { + if bytes.Equal(value.handle, emitter.tag_directives[i].handle) { + if allow_duplicates { + return true + } + return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive") + } + } + + // [Go] Do we actually need to copy this given garbage collection + // and the lack of deallocating destructors? + tag_copy := yaml_tag_directive_t{ + handle: make([]byte, len(value.handle)), + prefix: make([]byte, len(value.prefix)), + } + copy(tag_copy.handle, value.handle) + copy(tag_copy.prefix, value.prefix) + emitter.tag_directives = append(emitter.tag_directives, tag_copy) + return true +} + +// Increase the indentation level. +func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool, compact_seq bool) bool { + emitter.indents = append(emitter.indents, emitter.indent) + if emitter.indent < 0 { + if flow { + emitter.indent = emitter.best_indent + } else { + emitter.indent = 0 + } + } else if !indentless { + // [Go] This was changed so that indentations are more regular. + if emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE { + // The first indent inside a sequence will just skip the "- " indicator. + emitter.indent += 2 + } else { + // Everything else aligns to the chosen indentation. + emitter.indent = emitter.best_indent*((emitter.indent+emitter.best_indent)/emitter.best_indent) + } + if compact_seq { + emitter.indent = emitter.indent - 2 + } + } + return true +} + +// State dispatcher. +func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool { + switch emitter.state { + default: + case yaml_EMIT_STREAM_START_STATE: + return yaml_emitter_emit_stream_start(emitter, event) + + case yaml_EMIT_FIRST_DOCUMENT_START_STATE: + return yaml_emitter_emit_document_start(emitter, event, true) + + case yaml_EMIT_DOCUMENT_START_STATE: + return yaml_emitter_emit_document_start(emitter, event, false) + + case yaml_EMIT_DOCUMENT_CONTENT_STATE: + return yaml_emitter_emit_document_content(emitter, event) + + case yaml_EMIT_DOCUMENT_END_STATE: + return yaml_emitter_emit_document_end(emitter, event) + + case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE: + return yaml_emitter_emit_flow_sequence_item(emitter, event, true, false) + + case yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE: + return yaml_emitter_emit_flow_sequence_item(emitter, event, false, true) + + case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE: + return yaml_emitter_emit_flow_sequence_item(emitter, event, false, false) + + case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE: + return yaml_emitter_emit_flow_mapping_key(emitter, event, true, false) + + case yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE: + return yaml_emitter_emit_flow_mapping_key(emitter, event, false, true) + + case yaml_EMIT_FLOW_MAPPING_KEY_STATE: + return yaml_emitter_emit_flow_mapping_key(emitter, event, false, false) + + case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE: + return yaml_emitter_emit_flow_mapping_value(emitter, event, true) + + case yaml_EMIT_FLOW_MAPPING_VALUE_STATE: + return yaml_emitter_emit_flow_mapping_value(emitter, event, false) + + case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE: + return yaml_emitter_emit_block_sequence_item(emitter, event, true) + + case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE: + return yaml_emitter_emit_block_sequence_item(emitter, event, false) + + case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE: + return yaml_emitter_emit_block_mapping_key(emitter, event, true) + + case yaml_EMIT_BLOCK_MAPPING_KEY_STATE: + return yaml_emitter_emit_block_mapping_key(emitter, event, false) + + case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE: + return yaml_emitter_emit_block_mapping_value(emitter, event, true) + + case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE: + return yaml_emitter_emit_block_mapping_value(emitter, event, false) + + case yaml_EMIT_END_STATE: + return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END") + } + panic("invalid emitter state") +} + +// Expect STREAM-START. +func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if event.typ != yaml_STREAM_START_EVENT { + return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START") + } + if emitter.encoding == yaml_ANY_ENCODING { + emitter.encoding = event.encoding + if emitter.encoding == yaml_ANY_ENCODING { + emitter.encoding = yaml_UTF8_ENCODING + } + } + if emitter.best_indent < 2 || emitter.best_indent > 9 { + emitter.best_indent = 2 + } + if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 { + emitter.best_width = 80 + } + if emitter.best_width < 0 { + emitter.best_width = 1<<31 - 1 + } + if emitter.line_break == yaml_ANY_BREAK { + emitter.line_break = yaml_LN_BREAK + } + + emitter.indent = -1 + emitter.line = 0 + emitter.column = 0 + emitter.whitespace = true + emitter.indention = true + emitter.space_above = true + emitter.foot_indent = -1 + + if emitter.encoding != yaml_UTF8_ENCODING { + if !yaml_emitter_write_bom(emitter) { + return false + } + } + emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE + return true +} + +// Expect DOCUMENT-START or STREAM-END. +func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + + if event.typ == yaml_DOCUMENT_START_EVENT { + + if event.version_directive != nil { + if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) { + return false + } + } + + for i := 0; i < len(event.tag_directives); i++ { + tag_directive := &event.tag_directives[i] + if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) { + return false + } + if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) { + return false + } + } + + for i := 0; i < len(default_tag_directives); i++ { + tag_directive := &default_tag_directives[i] + if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) { + return false + } + } + + implicit := event.implicit + if !first || emitter.canonical { + implicit = false + } + + if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) { + if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + + if event.version_directive != nil { + implicit = false + if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + + if len(event.tag_directives) > 0 { + implicit = false + for i := 0; i < len(event.tag_directives); i++ { + tag_directive := &event.tag_directives[i] + if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) { + return false + } + if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) { + return false + } + if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + } + + if yaml_emitter_check_empty_document(emitter) { + implicit = false + } + if !implicit { + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) { + return false + } + if emitter.canonical || true { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + } + + if len(emitter.head_comment) > 0 { + if !yaml_emitter_process_head_comment(emitter) { + return false + } + if !put_break(emitter) { + return false + } + } + + emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE + return true + } + + if event.typ == yaml_STREAM_END_EVENT { + if emitter.open_ended { + if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_flush(emitter) { + return false + } + emitter.state = yaml_EMIT_END_STATE + return true + } + + return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END") +} + +// Expect the root node. +func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool { + emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE) + + if !yaml_emitter_process_head_comment(emitter) { + return false + } + if !yaml_emitter_emit_node(emitter, event, true, false, false, false) { + return false + } + if !yaml_emitter_process_line_comment(emitter, false) { + return false + } + if !yaml_emitter_process_foot_comment(emitter) { + return false + } + return true +} + +// Expect DOCUMENT-END. +func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if event.typ != yaml_DOCUMENT_END_EVENT { + return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END") + } + // [Go] Force document foot separation. + emitter.foot_indent = 0 + if !yaml_emitter_process_foot_comment(emitter) { + return false + } + emitter.foot_indent = -1 + if !yaml_emitter_write_indent(emitter) { + return false + } + if !event.implicit { + // [Go] Allocate the slice elsewhere. + if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_flush(emitter) { + return false + } + emitter.state = yaml_EMIT_DOCUMENT_START_STATE + emitter.tag_directives = emitter.tag_directives[:0] + return true +} + +// Expect a flow item node. +func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool { + if first { + if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) { + return false + } + if !yaml_emitter_increase_indent(emitter, true, false, false) { + return false + } + emitter.flow_level++ + } + + if event.typ == yaml_SEQUENCE_END_EVENT { + if emitter.canonical && !first && !trail { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + } + emitter.flow_level-- + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + if emitter.column == 0 || emitter.canonical && !first { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) { + return false + } + if !yaml_emitter_process_line_comment(emitter, false) { + return false + } + if !yaml_emitter_process_foot_comment(emitter) { + return false + } + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + + return true + } + + if !first && !trail { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + } + + if !yaml_emitter_process_head_comment(emitter) { + return false + } + if emitter.column == 0 { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + + if emitter.canonical || emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { + emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE) + } else { + emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE) + } + if !yaml_emitter_emit_node(emitter, event, false, true, false, false) { + return false + } + if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + } + if !yaml_emitter_process_line_comment(emitter, false) { + return false + } + if !yaml_emitter_process_foot_comment(emitter) { + return false + } + return true +} + +// Expect a flow key node. +func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool { + if first { + if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) { + return false + } + if !yaml_emitter_increase_indent(emitter, true, false, false) { + return false + } + emitter.flow_level++ + } + + if event.typ == yaml_MAPPING_END_EVENT { + if (emitter.canonical || len(emitter.head_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0) && !first && !trail { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + } + if !yaml_emitter_process_head_comment(emitter) { + return false + } + emitter.flow_level-- + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + if emitter.canonical && !first { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) { + return false + } + if !yaml_emitter_process_line_comment(emitter, false) { + return false + } + if !yaml_emitter_process_foot_comment(emitter) { + return false + } + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true + } + + if !first && !trail { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + } + + if !yaml_emitter_process_head_comment(emitter) { + return false + } + + if emitter.column == 0 { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + + if emitter.canonical || emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + + if !emitter.canonical && yaml_emitter_check_simple_key(emitter) { + emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, true) + } + if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) { + return false + } + emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, false) +} + +// Expect a flow value node. +func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { + if simple { + if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { + return false + } + } else { + if emitter.canonical || emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) { + return false + } + } + if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { + emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE) + } else { + emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE) + } + if !yaml_emitter_emit_node(emitter, event, false, false, true, false) { + return false + } + if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + } + if !yaml_emitter_process_line_comment(emitter, false) { + return false + } + if !yaml_emitter_process_foot_comment(emitter) { + return false + } + return true +} + +// Expect a block item node. +func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + if first { + seq := emitter.mapping_context && (emitter.column == 0 || !emitter.indention) && + emitter.compact_sequence_indent + if !yaml_emitter_increase_indent(emitter, false, false, seq){ + return false + } + } + if event.typ == yaml_SEQUENCE_END_EVENT { + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true + } + if !yaml_emitter_process_head_comment(emitter) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) { + return false + } + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE) + if !yaml_emitter_emit_node(emitter, event, false, true, false, false) { + return false + } + if !yaml_emitter_process_line_comment(emitter, false) { + return false + } + if !yaml_emitter_process_foot_comment(emitter) { + return false + } + return true +} + +// Expect a block key node. +func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + if first { + if !yaml_emitter_increase_indent(emitter, false, false, false) { + return false + } + } + if !yaml_emitter_process_head_comment(emitter) { + return false + } + if event.typ == yaml_MAPPING_END_EVENT { + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true + } + if !yaml_emitter_write_indent(emitter) { + return false + } + if len(emitter.line_comment) > 0 { + // [Go] A line comment was provided for the key. That's unusual as the + // scanner associates line comments with the value. Either way, + // save the line comment and render it appropriately later. + emitter.key_line_comment = emitter.line_comment + emitter.line_comment = nil + } + if yaml_emitter_check_simple_key(emitter) { + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, true) + } + if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) { + return false + } + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, false) +} + +// Expect a block value node. +func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { + if simple { + if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { + return false + } + } else { + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) { + return false + } + } + if len(emitter.key_line_comment) > 0 { + // [Go] Line comments are generally associated with the value, but when there's + // no value on the same line as a mapping key they end up attached to the + // key itself. + if event.typ == yaml_SCALAR_EVENT { + if len(emitter.line_comment) == 0 { + // A scalar is coming and it has no line comments by itself yet, + // so just let it handle the line comment as usual. If it has a + // line comment, we can't have both so the one from the key is lost. + emitter.line_comment = emitter.key_line_comment + emitter.key_line_comment = nil + } + } else if event.sequence_style() != yaml_FLOW_SEQUENCE_STYLE && (event.typ == yaml_MAPPING_START_EVENT || event.typ == yaml_SEQUENCE_START_EVENT) { + // An indented block follows, so write the comment right now. + emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment + if !yaml_emitter_process_line_comment(emitter, false) { + return false + } + emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment + } + } + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE) + if !yaml_emitter_emit_node(emitter, event, false, false, true, false) { + return false + } + if !yaml_emitter_process_line_comment(emitter, false) { + return false + } + if !yaml_emitter_process_foot_comment(emitter) { + return false + } + return true +} + +func yaml_emitter_silent_nil_event(emitter *yaml_emitter_t, event *yaml_event_t) bool { + return event.typ == yaml_SCALAR_EVENT && event.implicit && !emitter.canonical && len(emitter.scalar_data.value) == 0 +} + +// Expect a node. +func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t, + root bool, sequence bool, mapping bool, simple_key bool) bool { + + emitter.root_context = root + emitter.sequence_context = sequence + emitter.mapping_context = mapping + emitter.simple_key_context = simple_key + + switch event.typ { + case yaml_ALIAS_EVENT: + return yaml_emitter_emit_alias(emitter, event) + case yaml_SCALAR_EVENT: + return yaml_emitter_emit_scalar(emitter, event) + case yaml_SEQUENCE_START_EVENT: + return yaml_emitter_emit_sequence_start(emitter, event) + case yaml_MAPPING_START_EVENT: + return yaml_emitter_emit_mapping_start(emitter, event) + default: + return yaml_emitter_set_emitter_error(emitter, + fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ)) + } +} + +// Expect ALIAS. +func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_process_anchor(emitter) { + return false + } + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true +} + +// Expect SCALAR. +func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_select_scalar_style(emitter, event) { + return false + } + if !yaml_emitter_process_anchor(emitter) { + return false + } + if !yaml_emitter_process_tag(emitter) { + return false + } + if !yaml_emitter_increase_indent(emitter, true, false, false) { + return false + } + if !yaml_emitter_process_scalar(emitter) { + return false + } + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true +} + +// Expect SEQUENCE-START. +func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_process_anchor(emitter) { + return false + } + if !yaml_emitter_process_tag(emitter) { + return false + } + if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE || + yaml_emitter_check_empty_sequence(emitter) { + emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE + } else { + emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE + } + return true +} + +// Expect MAPPING-START. +func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_process_anchor(emitter) { + return false + } + if !yaml_emitter_process_tag(emitter) { + return false + } + if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE || + yaml_emitter_check_empty_mapping(emitter) { + emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE + } else { + emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE + } + return true +} + +// Check if the document content is an empty scalar. +func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool { + return false // [Go] Huh? +} + +// Check if the next events represent an empty sequence. +func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool { + if len(emitter.events)-emitter.events_head < 2 { + return false + } + return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT && + emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT +} + +// Check if the next events represent an empty mapping. +func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool { + if len(emitter.events)-emitter.events_head < 2 { + return false + } + return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT && + emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT +} + +// Check if the next node can be expressed as a simple key. +func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool { + length := 0 + switch emitter.events[emitter.events_head].typ { + case yaml_ALIAS_EVENT: + length += len(emitter.anchor_data.anchor) + case yaml_SCALAR_EVENT: + if emitter.scalar_data.multiline { + return false + } + length += len(emitter.anchor_data.anchor) + + len(emitter.tag_data.handle) + + len(emitter.tag_data.suffix) + + len(emitter.scalar_data.value) + case yaml_SEQUENCE_START_EVENT: + if !yaml_emitter_check_empty_sequence(emitter) { + return false + } + length += len(emitter.anchor_data.anchor) + + len(emitter.tag_data.handle) + + len(emitter.tag_data.suffix) + case yaml_MAPPING_START_EVENT: + if !yaml_emitter_check_empty_mapping(emitter) { + return false + } + length += len(emitter.anchor_data.anchor) + + len(emitter.tag_data.handle) + + len(emitter.tag_data.suffix) + default: + return false + } + return length <= 128 +} + +// Determine an acceptable scalar style. +func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool { + + no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 + if no_tag && !event.implicit && !event.quoted_implicit { + return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified") + } + + style := event.scalar_style() + if style == yaml_ANY_SCALAR_STYLE { + style = yaml_PLAIN_SCALAR_STYLE + } + if emitter.canonical { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + if emitter.simple_key_context && emitter.scalar_data.multiline { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + + if style == yaml_PLAIN_SCALAR_STYLE { + if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed || + emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed { + style = yaml_SINGLE_QUOTED_SCALAR_STYLE + } + if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) { + style = yaml_SINGLE_QUOTED_SCALAR_STYLE + } + if no_tag && !event.implicit { + style = yaml_SINGLE_QUOTED_SCALAR_STYLE + } + } + if style == yaml_SINGLE_QUOTED_SCALAR_STYLE { + if !emitter.scalar_data.single_quoted_allowed { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + } + if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE { + if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + } + + if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE { + emitter.tag_data.handle = []byte{'!'} + } + emitter.scalar_data.style = style + return true +} + +// Write an anchor. +func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool { + if emitter.anchor_data.anchor == nil { + return true + } + c := []byte{'&'} + if emitter.anchor_data.alias { + c[0] = '*' + } + if !yaml_emitter_write_indicator(emitter, c, true, false, false) { + return false + } + return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor) +} + +// Write a tag. +func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool { + if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 { + return true + } + if len(emitter.tag_data.handle) > 0 { + if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) { + return false + } + if len(emitter.tag_data.suffix) > 0 { + if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { + return false + } + } + } else { + // [Go] Allocate these slices elsewhere. + if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) { + return false + } + if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) { + return false + } + } + return true +} + +// Write a scalar. +func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool { + switch emitter.scalar_data.style { + case yaml_PLAIN_SCALAR_STYLE: + return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) + + case yaml_SINGLE_QUOTED_SCALAR_STYLE: + return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) + + case yaml_DOUBLE_QUOTED_SCALAR_STYLE: + return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) + + case yaml_LITERAL_SCALAR_STYLE: + return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value) + + case yaml_FOLDED_SCALAR_STYLE: + return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value) + } + panic("unknown scalar style") +} + +// Write a head comment. +func yaml_emitter_process_head_comment(emitter *yaml_emitter_t) bool { + if len(emitter.tail_comment) > 0 { + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_comment(emitter, emitter.tail_comment) { + return false + } + emitter.tail_comment = emitter.tail_comment[:0] + emitter.foot_indent = emitter.indent + if emitter.foot_indent < 0 { + emitter.foot_indent = 0 + } + } + + if len(emitter.head_comment) == 0 { + return true + } + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_comment(emitter, emitter.head_comment) { + return false + } + emitter.head_comment = emitter.head_comment[:0] + return true +} + +// Write an line comment. +func yaml_emitter_process_line_comment(emitter *yaml_emitter_t, linebreak bool) bool { + if len(emitter.line_comment) == 0 { + if linebreak && !put_break(emitter) { + return false + } + return true + } + if !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + if !yaml_emitter_write_comment(emitter, emitter.line_comment) { + return false + } + emitter.line_comment = emitter.line_comment[:0] + return true +} + +// Write a foot comment. +func yaml_emitter_process_foot_comment(emitter *yaml_emitter_t) bool { + if len(emitter.foot_comment) == 0 { + return true + } + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_comment(emitter, emitter.foot_comment) { + return false + } + emitter.foot_comment = emitter.foot_comment[:0] + emitter.foot_indent = emitter.indent + if emitter.foot_indent < 0 { + emitter.foot_indent = 0 + } + return true +} + +// Check if a %YAML directive is valid. +func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool { + if version_directive.major != 1 || version_directive.minor != 1 { + return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive") + } + return true +} + +// Check if a %TAG directive is valid. +func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool { + handle := tag_directive.handle + prefix := tag_directive.prefix + if len(handle) == 0 { + return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty") + } + if handle[0] != '!' { + return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'") + } + if handle[len(handle)-1] != '!' { + return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'") + } + for i := 1; i < len(handle)-1; i += width(handle[i]) { + if !is_alpha(handle, i) { + return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only") + } + } + if len(prefix) == 0 { + return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty") + } + return true +} + +// Check if an anchor is valid. +func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool { + if len(anchor) == 0 { + problem := "anchor value must not be empty" + if alias { + problem = "alias value must not be empty" + } + return yaml_emitter_set_emitter_error(emitter, problem) + } + for i := 0; i < len(anchor); i += width(anchor[i]) { + if !is_alpha(anchor, i) { + problem := "anchor value must contain alphanumerical characters only" + if alias { + problem = "alias value must contain alphanumerical characters only" + } + return yaml_emitter_set_emitter_error(emitter, problem) + } + } + emitter.anchor_data.anchor = anchor + emitter.anchor_data.alias = alias + return true +} + +// Check if a tag is valid. +func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool { + if len(tag) == 0 { + return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty") + } + for i := 0; i < len(emitter.tag_directives); i++ { + tag_directive := &emitter.tag_directives[i] + if bytes.HasPrefix(tag, tag_directive.prefix) { + emitter.tag_data.handle = tag_directive.handle + emitter.tag_data.suffix = tag[len(tag_directive.prefix):] + return true + } + } + emitter.tag_data.suffix = tag + return true +} + +// Check if a scalar is valid. +func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool { + var ( + block_indicators = false + flow_indicators = false + line_breaks = false + special_characters = false + tab_characters = false + + leading_space = false + leading_break = false + trailing_space = false + trailing_break = false + break_space = false + space_break = false + + preceded_by_whitespace = false + followed_by_whitespace = false + previous_space = false + previous_break = false + ) + + emitter.scalar_data.value = value + + if len(value) == 0 { + emitter.scalar_data.multiline = false + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = true + emitter.scalar_data.single_quoted_allowed = true + emitter.scalar_data.block_allowed = false + return true + } + + if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) { + block_indicators = true + flow_indicators = true + } + + preceded_by_whitespace = true + for i, w := 0, 0; i < len(value); i += w { + w = width(value[i]) + followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w) + + if i == 0 { + switch value[i] { + case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`': + flow_indicators = true + block_indicators = true + case '?', ':': + flow_indicators = true + if followed_by_whitespace { + block_indicators = true + } + case '-': + if followed_by_whitespace { + flow_indicators = true + block_indicators = true + } + } + } else { + switch value[i] { + case ',', '?', '[', ']', '{', '}': + flow_indicators = true + case ':': + flow_indicators = true + if followed_by_whitespace { + block_indicators = true + } + case '#': + if preceded_by_whitespace { + flow_indicators = true + block_indicators = true + } + } + } + + if value[i] == '\t' { + tab_characters = true + } else if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode { + special_characters = true + } + if is_space(value, i) { + if i == 0 { + leading_space = true + } + if i+width(value[i]) == len(value) { + trailing_space = true + } + if previous_break { + break_space = true + } + previous_space = true + previous_break = false + } else if is_break(value, i) { + line_breaks = true + if i == 0 { + leading_break = true + } + if i+width(value[i]) == len(value) { + trailing_break = true + } + if previous_space { + space_break = true + } + previous_space = false + previous_break = true + } else { + previous_space = false + previous_break = false + } + + // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition. + preceded_by_whitespace = is_blankz(value, i) + } + + emitter.scalar_data.multiline = line_breaks + emitter.scalar_data.flow_plain_allowed = true + emitter.scalar_data.block_plain_allowed = true + emitter.scalar_data.single_quoted_allowed = true + emitter.scalar_data.block_allowed = true + + if leading_space || leading_break || trailing_space || trailing_break { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + } + if trailing_space { + emitter.scalar_data.block_allowed = false + } + if break_space { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + emitter.scalar_data.single_quoted_allowed = false + } + if space_break || tab_characters || special_characters { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + emitter.scalar_data.single_quoted_allowed = false + } + if space_break || special_characters { + emitter.scalar_data.block_allowed = false + } + if line_breaks { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + } + if flow_indicators { + emitter.scalar_data.flow_plain_allowed = false + } + if block_indicators { + emitter.scalar_data.block_plain_allowed = false + } + return true +} + +// Check if the event data is valid. +func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool { + + emitter.anchor_data.anchor = nil + emitter.tag_data.handle = nil + emitter.tag_data.suffix = nil + emitter.scalar_data.value = nil + + if len(event.head_comment) > 0 { + emitter.head_comment = event.head_comment + } + if len(event.line_comment) > 0 { + emitter.line_comment = event.line_comment + } + if len(event.foot_comment) > 0 { + emitter.foot_comment = event.foot_comment + } + if len(event.tail_comment) > 0 { + emitter.tail_comment = event.tail_comment + } + + switch event.typ { + case yaml_ALIAS_EVENT: + if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) { + return false + } + + case yaml_SCALAR_EVENT: + if len(event.anchor) > 0 { + if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { + return false + } + } + if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) { + if !yaml_emitter_analyze_tag(emitter, event.tag) { + return false + } + } + if !yaml_emitter_analyze_scalar(emitter, event.value) { + return false + } + + case yaml_SEQUENCE_START_EVENT: + if len(event.anchor) > 0 { + if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { + return false + } + } + if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { + if !yaml_emitter_analyze_tag(emitter, event.tag) { + return false + } + } + + case yaml_MAPPING_START_EVENT: + if len(event.anchor) > 0 { + if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { + return false + } + } + if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { + if !yaml_emitter_analyze_tag(emitter, event.tag) { + return false + } + } + } + return true +} + +// Write the BOM character. +func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool { + if !flush(emitter) { + return false + } + pos := emitter.buffer_pos + emitter.buffer[pos+0] = '\xEF' + emitter.buffer[pos+1] = '\xBB' + emitter.buffer[pos+2] = '\xBF' + emitter.buffer_pos += 3 + return true +} + +func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool { + indent := emitter.indent + if indent < 0 { + indent = 0 + } + if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) { + if !put_break(emitter) { + return false + } + } + if emitter.foot_indent == indent { + if !put_break(emitter) { + return false + } + } + for emitter.column < indent { + if !put(emitter, ' ') { + return false + } + } + emitter.whitespace = true + //emitter.indention = true + emitter.space_above = false + emitter.foot_indent = -1 + return true +} + +func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool { + if need_whitespace && !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + if !write_all(emitter, indicator) { + return false + } + emitter.whitespace = is_whitespace + emitter.indention = (emitter.indention && is_indention) + emitter.open_ended = false + return true +} + +func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool { + if !write_all(emitter, value) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool { + if !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + if !write_all(emitter, value) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool { + if need_whitespace && !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + for i := 0; i < len(value); { + var must_write bool + switch value[i] { + case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']': + must_write = true + default: + must_write = is_alpha(value, i) + } + if must_write { + if !write(emitter, value, &i) { + return false + } + } else { + w := width(value[i]) + for k := 0; k < w; k++ { + octet := value[i] + i++ + if !put(emitter, '%') { + return false + } + + c := octet >> 4 + if c < 10 { + c += '0' + } else { + c += 'A' - 10 + } + if !put(emitter, c) { + return false + } + + c = octet & 0x0f + if c < 10 { + c += '0' + } else { + c += 'A' - 10 + } + if !put(emitter, c) { + return false + } + } + } + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { + if len(value) > 0 && !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + + spaces := false + breaks := false + for i := 0; i < len(value); { + if is_space(value, i) { + if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) { + if !yaml_emitter_write_indent(emitter) { + return false + } + i += width(value[i]) + } else { + if !write(emitter, value, &i) { + return false + } + } + spaces = true + } else if is_break(value, i) { + if !breaks && value[i] == '\n' { + if !put_break(emitter) { + return false + } + } + if !write_break(emitter, value, &i) { + return false + } + //emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !write(emitter, value, &i) { + return false + } + emitter.indention = false + spaces = false + breaks = false + } + } + + if len(value) > 0 { + emitter.whitespace = false + } + emitter.indention = false + if emitter.root_context { + emitter.open_ended = true + } + + return true +} + +func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { + + if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) { + return false + } + + spaces := false + breaks := false + for i := 0; i < len(value); { + if is_space(value, i) { + if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) { + if !yaml_emitter_write_indent(emitter) { + return false + } + i += width(value[i]) + } else { + if !write(emitter, value, &i) { + return false + } + } + spaces = true + } else if is_break(value, i) { + if !breaks && value[i] == '\n' { + if !put_break(emitter) { + return false + } + } + if !write_break(emitter, value, &i) { + return false + } + //emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if value[i] == '\'' { + if !put(emitter, '\'') { + return false + } + } + if !write(emitter, value, &i) { + return false + } + emitter.indention = false + spaces = false + breaks = false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { + spaces := false + if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) { + return false + } + + for i := 0; i < len(value); { + if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) || + is_bom(value, i) || is_break(value, i) || + value[i] == '"' || value[i] == '\\' { + + octet := value[i] + + var w int + var v rune + switch { + case octet&0x80 == 0x00: + w, v = 1, rune(octet&0x7F) + case octet&0xE0 == 0xC0: + w, v = 2, rune(octet&0x1F) + case octet&0xF0 == 0xE0: + w, v = 3, rune(octet&0x0F) + case octet&0xF8 == 0xF0: + w, v = 4, rune(octet&0x07) + } + for k := 1; k < w; k++ { + octet = value[i+k] + v = (v << 6) + (rune(octet) & 0x3F) + } + i += w + + if !put(emitter, '\\') { + return false + } + + var ok bool + switch v { + case 0x00: + ok = put(emitter, '0') + case 0x07: + ok = put(emitter, 'a') + case 0x08: + ok = put(emitter, 'b') + case 0x09: + ok = put(emitter, 't') + case 0x0A: + ok = put(emitter, 'n') + case 0x0b: + ok = put(emitter, 'v') + case 0x0c: + ok = put(emitter, 'f') + case 0x0d: + ok = put(emitter, 'r') + case 0x1b: + ok = put(emitter, 'e') + case 0x22: + ok = put(emitter, '"') + case 0x5c: + ok = put(emitter, '\\') + case 0x85: + ok = put(emitter, 'N') + case 0xA0: + ok = put(emitter, '_') + case 0x2028: + ok = put(emitter, 'L') + case 0x2029: + ok = put(emitter, 'P') + default: + if v <= 0xFF { + ok = put(emitter, 'x') + w = 2 + } else if v <= 0xFFFF { + ok = put(emitter, 'u') + w = 4 + } else { + ok = put(emitter, 'U') + w = 8 + } + for k := (w - 1) * 4; ok && k >= 0; k -= 4 { + digit := byte((v >> uint(k)) & 0x0F) + if digit < 10 { + ok = put(emitter, digit+'0') + } else { + ok = put(emitter, digit+'A'-10) + } + } + } + if !ok { + return false + } + spaces = false + } else if is_space(value, i) { + if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 { + if !yaml_emitter_write_indent(emitter) { + return false + } + if is_space(value, i+1) { + if !put(emitter, '\\') { + return false + } + } + i += width(value[i]) + } else if !write(emitter, value, &i) { + return false + } + spaces = true + } else { + if !write(emitter, value, &i) { + return false + } + spaces = false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool { + if is_space(value, 0) || is_break(value, 0) { + indent_hint := []byte{'0' + byte(emitter.best_indent)} + if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) { + return false + } + } + + emitter.open_ended = false + + var chomp_hint [1]byte + if len(value) == 0 { + chomp_hint[0] = '-' + } else { + i := len(value) - 1 + for value[i]&0xC0 == 0x80 { + i-- + } + if !is_break(value, i) { + chomp_hint[0] = '-' + } else if i == 0 { + chomp_hint[0] = '+' + emitter.open_ended = true + } else { + i-- + for value[i]&0xC0 == 0x80 { + i-- + } + if is_break(value, i) { + chomp_hint[0] = '+' + emitter.open_ended = true + } + } + } + if chomp_hint[0] != 0 { + if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) { + return false + } + } + return true +} + +func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool { + if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) { + return false + } + if !yaml_emitter_write_block_scalar_hints(emitter, value) { + return false + } + if !yaml_emitter_process_line_comment(emitter, true) { + return false + } + //emitter.indention = true + emitter.whitespace = true + breaks := true + for i := 0; i < len(value); { + if is_break(value, i) { + if !write_break(emitter, value, &i) { + return false + } + //emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !write(emitter, value, &i) { + return false + } + emitter.indention = false + breaks = false + } + } + + return true +} + +func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool { + if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) { + return false + } + if !yaml_emitter_write_block_scalar_hints(emitter, value) { + return false + } + if !yaml_emitter_process_line_comment(emitter, true) { + return false + } + + //emitter.indention = true + emitter.whitespace = true + + breaks := true + leading_spaces := true + for i := 0; i < len(value); { + if is_break(value, i) { + if !breaks && !leading_spaces && value[i] == '\n' { + k := 0 + for is_break(value, k) { + k += width(value[k]) + } + if !is_blankz(value, k) { + if !put_break(emitter) { + return false + } + } + } + if !write_break(emitter, value, &i) { + return false + } + //emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + leading_spaces = is_blank(value, i) + } + if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + i += width(value[i]) + } else { + if !write(emitter, value, &i) { + return false + } + } + emitter.indention = false + breaks = false + } + } + return true +} + +func yaml_emitter_write_comment(emitter *yaml_emitter_t, comment []byte) bool { + breaks := false + pound := false + for i := 0; i < len(comment); { + if is_break(comment, i) { + if !write_break(emitter, comment, &i) { + return false + } + //emitter.indention = true + breaks = true + pound = false + } else { + if breaks && !yaml_emitter_write_indent(emitter) { + return false + } + if !pound { + if comment[i] != '#' && (!put(emitter, '#') || !put(emitter, ' ')) { + return false + } + pound = true + } + if !write(emitter, comment, &i) { + return false + } + emitter.indention = false + breaks = false + } + } + if !breaks && !put_break(emitter) { + return false + } + + emitter.whitespace = true + //emitter.indention = true + return true +} diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/encode.go b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/encode.go new file mode 100644 index 000000000..de9e72a3e --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/encode.go @@ -0,0 +1,577 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package yaml + +import ( + "encoding" + "fmt" + "io" + "reflect" + "regexp" + "sort" + "strconv" + "strings" + "time" + "unicode/utf8" +) + +type encoder struct { + emitter yaml_emitter_t + event yaml_event_t + out []byte + flow bool + indent int + doneInit bool +} + +func newEncoder() *encoder { + e := &encoder{} + yaml_emitter_initialize(&e.emitter) + yaml_emitter_set_output_string(&e.emitter, &e.out) + yaml_emitter_set_unicode(&e.emitter, true) + return e +} + +func newEncoderWithWriter(w io.Writer) *encoder { + e := &encoder{} + yaml_emitter_initialize(&e.emitter) + yaml_emitter_set_output_writer(&e.emitter, w) + yaml_emitter_set_unicode(&e.emitter, true) + return e +} + +func (e *encoder) init() { + if e.doneInit { + return + } + if e.indent == 0 { + e.indent = 4 + } + e.emitter.best_indent = e.indent + yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING) + e.emit() + e.doneInit = true +} + +func (e *encoder) finish() { + e.emitter.open_ended = false + yaml_stream_end_event_initialize(&e.event) + e.emit() +} + +func (e *encoder) destroy() { + yaml_emitter_delete(&e.emitter) +} + +func (e *encoder) emit() { + // This will internally delete the e.event value. + e.must(yaml_emitter_emit(&e.emitter, &e.event)) +} + +func (e *encoder) must(ok bool) { + if !ok { + msg := e.emitter.problem + if msg == "" { + msg = "unknown problem generating YAML content" + } + failf("%s", msg) + } +} + +func (e *encoder) marshalDoc(tag string, in reflect.Value) { + e.init() + var node *Node + if in.IsValid() { + node, _ = in.Interface().(*Node) + } + if node != nil && node.Kind == DocumentNode { + e.nodev(in) + } else { + yaml_document_start_event_initialize(&e.event, nil, nil, true) + e.emit() + e.marshal(tag, in) + yaml_document_end_event_initialize(&e.event, true) + e.emit() + } +} + +func (e *encoder) marshal(tag string, in reflect.Value) { + tag = shortTag(tag) + if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() { + e.nilv() + return + } + iface := in.Interface() + switch value := iface.(type) { + case *Node: + e.nodev(in) + return + case Node: + if !in.CanAddr() { + var n = reflect.New(in.Type()).Elem() + n.Set(in) + in = n + } + e.nodev(in.Addr()) + return + case time.Time: + e.timev(tag, in) + return + case *time.Time: + e.timev(tag, in.Elem()) + return + case time.Duration: + e.stringv(tag, reflect.ValueOf(value.String())) + return + case Marshaler: + v, err := value.MarshalYAML() + if err != nil { + fail(err) + } + if v == nil { + e.nilv() + return + } + e.marshal(tag, reflect.ValueOf(v)) + return + case encoding.TextMarshaler: + text, err := value.MarshalText() + if err != nil { + fail(err) + } + in = reflect.ValueOf(string(text)) + case nil: + e.nilv() + return + } + switch in.Kind() { + case reflect.Interface: + e.marshal(tag, in.Elem()) + case reflect.Map: + e.mapv(tag, in) + case reflect.Ptr: + e.marshal(tag, in.Elem()) + case reflect.Struct: + e.structv(tag, in) + case reflect.Slice, reflect.Array: + e.slicev(tag, in) + case reflect.String: + e.stringv(tag, in) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + e.intv(tag, in) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + e.uintv(tag, in) + case reflect.Float32, reflect.Float64: + e.floatv(tag, in) + case reflect.Bool: + e.boolv(tag, in) + default: + panic("cannot marshal type: " + in.Type().String()) + } +} + +func (e *encoder) mapv(tag string, in reflect.Value) { + e.mappingv(tag, func() { + keys := keyList(in.MapKeys()) + sort.Sort(keys) + for _, k := range keys { + e.marshal("", k) + e.marshal("", in.MapIndex(k)) + } + }) +} + +func (e *encoder) fieldByIndex(v reflect.Value, index []int) (field reflect.Value) { + for _, num := range index { + for { + if v.Kind() == reflect.Ptr { + if v.IsNil() { + return reflect.Value{} + } + v = v.Elem() + continue + } + break + } + v = v.Field(num) + } + return v +} + +func (e *encoder) structv(tag string, in reflect.Value) { + sinfo, err := getStructInfo(in.Type()) + if err != nil { + panic(err) + } + e.mappingv(tag, func() { + for _, info := range sinfo.FieldsList { + var value reflect.Value + if info.Inline == nil { + value = in.Field(info.Num) + } else { + value = e.fieldByIndex(in, info.Inline) + if !value.IsValid() { + continue + } + } + if info.OmitEmpty && isZero(value) { + continue + } + e.marshal("", reflect.ValueOf(info.Key)) + e.flow = info.Flow + e.marshal("", value) + } + if sinfo.InlineMap >= 0 { + m := in.Field(sinfo.InlineMap) + if m.Len() > 0 { + e.flow = false + keys := keyList(m.MapKeys()) + sort.Sort(keys) + for _, k := range keys { + if _, found := sinfo.FieldsMap[k.String()]; found { + panic(fmt.Sprintf("cannot have key %q in inlined map: conflicts with struct field", k.String())) + } + e.marshal("", k) + e.flow = false + e.marshal("", m.MapIndex(k)) + } + } + } + }) +} + +func (e *encoder) mappingv(tag string, f func()) { + implicit := tag == "" + style := yaml_BLOCK_MAPPING_STYLE + if e.flow { + e.flow = false + style = yaml_FLOW_MAPPING_STYLE + } + yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style) + e.emit() + f() + yaml_mapping_end_event_initialize(&e.event) + e.emit() +} + +func (e *encoder) slicev(tag string, in reflect.Value) { + implicit := tag == "" + style := yaml_BLOCK_SEQUENCE_STYLE + if e.flow { + e.flow = false + style = yaml_FLOW_SEQUENCE_STYLE + } + e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) + e.emit() + n := in.Len() + for i := 0; i < n; i++ { + e.marshal("", in.Index(i)) + } + e.must(yaml_sequence_end_event_initialize(&e.event)) + e.emit() +} + +// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. +// +// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported +// in YAML 1.2 and by this package, but these should be marshalled quoted for +// the time being for compatibility with other parsers. +func isBase60Float(s string) (result bool) { + // Fast path. + if s == "" { + return false + } + c := s[0] + if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 { + return false + } + // Do the full match. + return base60float.MatchString(s) +} + +// From http://yaml.org/type/float.html, except the regular expression there +// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix. +var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`) + +// isOldBool returns whether s is bool notation as defined in YAML 1.1. +// +// We continue to force strings that YAML 1.1 would interpret as booleans to be +// rendered as quotes strings so that the marshalled output valid for YAML 1.1 +// parsing. +func isOldBool(s string) (result bool) { + switch s { + case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON", + "n", "N", "no", "No", "NO", "off", "Off", "OFF": + return true + default: + return false + } +} + +func (e *encoder) stringv(tag string, in reflect.Value) { + var style yaml_scalar_style_t + s := in.String() + canUsePlain := true + switch { + case !utf8.ValidString(s): + if tag == binaryTag { + failf("explicitly tagged !!binary data must be base64-encoded") + } + if tag != "" { + failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag)) + } + // It can't be encoded directly as YAML so use a binary tag + // and encode it as base64. + tag = binaryTag + s = encodeBase64(s) + case tag == "": + // Check to see if it would resolve to a specific + // tag when encoded unquoted. If it doesn't, + // there's no need to quote it. + rtag, _ := resolve("", s) + canUsePlain = rtag == strTag && !(isBase60Float(s) || isOldBool(s)) + } + // Note: it's possible for user code to emit invalid YAML + // if they explicitly specify a tag and a string containing + // text that's incompatible with that tag. + switch { + case strings.Contains(s, "\n"): + if e.flow { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } else { + style = yaml_LITERAL_SCALAR_STYLE + } + case canUsePlain: + style = yaml_PLAIN_SCALAR_STYLE + default: + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + e.emitScalar(s, "", tag, style, nil, nil, nil, nil) +} + +func (e *encoder) boolv(tag string, in reflect.Value) { + var s string + if in.Bool() { + s = "true" + } else { + s = "false" + } + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) +} + +func (e *encoder) intv(tag string, in reflect.Value) { + s := strconv.FormatInt(in.Int(), 10) + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) +} + +func (e *encoder) uintv(tag string, in reflect.Value) { + s := strconv.FormatUint(in.Uint(), 10) + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) +} + +func (e *encoder) timev(tag string, in reflect.Value) { + t := in.Interface().(time.Time) + s := t.Format(time.RFC3339Nano) + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) +} + +func (e *encoder) floatv(tag string, in reflect.Value) { + // Issue #352: When formatting, use the precision of the underlying value + precision := 64 + if in.Kind() == reflect.Float32 { + precision = 32 + } + + s := strconv.FormatFloat(in.Float(), 'g', -1, precision) + switch s { + case "+Inf": + s = ".inf" + case "-Inf": + s = "-.inf" + case "NaN": + s = ".nan" + } + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) +} + +func (e *encoder) nilv() { + e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) +} + +func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t, head, line, foot, tail []byte) { + // TODO Kill this function. Replace all initialize calls by their underlining Go literals. + implicit := tag == "" + if !implicit { + tag = longTag(tag) + } + e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)) + e.event.head_comment = head + e.event.line_comment = line + e.event.foot_comment = foot + e.event.tail_comment = tail + e.emit() +} + +func (e *encoder) nodev(in reflect.Value) { + e.node(in.Interface().(*Node), "") +} + +func (e *encoder) node(node *Node, tail string) { + // Zero nodes behave as nil. + if node.Kind == 0 && node.IsZero() { + e.nilv() + return + } + + // If the tag was not explicitly requested, and dropping it won't change the + // implicit tag of the value, don't include it in the presentation. + var tag = node.Tag + var stag = shortTag(tag) + var forceQuoting bool + if tag != "" && node.Style&TaggedStyle == 0 { + if node.Kind == ScalarNode { + if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 { + tag = "" + } else { + rtag, _ := resolve("", node.Value) + if rtag == stag { + tag = "" + } else if stag == strTag { + tag = "" + forceQuoting = true + } + } + } else { + var rtag string + switch node.Kind { + case MappingNode: + rtag = mapTag + case SequenceNode: + rtag = seqTag + } + if rtag == stag { + tag = "" + } + } + } + + switch node.Kind { + case DocumentNode: + yaml_document_start_event_initialize(&e.event, nil, nil, true) + e.event.head_comment = []byte(node.HeadComment) + e.emit() + for _, node := range node.Content { + e.node(node, "") + } + yaml_document_end_event_initialize(&e.event, true) + e.event.foot_comment = []byte(node.FootComment) + e.emit() + + case SequenceNode: + style := yaml_BLOCK_SEQUENCE_STYLE + if node.Style&FlowStyle != 0 { + style = yaml_FLOW_SEQUENCE_STYLE + } + e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style)) + e.event.head_comment = []byte(node.HeadComment) + e.emit() + for _, node := range node.Content { + e.node(node, "") + } + e.must(yaml_sequence_end_event_initialize(&e.event)) + e.event.line_comment = []byte(node.LineComment) + e.event.foot_comment = []byte(node.FootComment) + e.emit() + + case MappingNode: + style := yaml_BLOCK_MAPPING_STYLE + if node.Style&FlowStyle != 0 { + style = yaml_FLOW_MAPPING_STYLE + } + yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style) + e.event.tail_comment = []byte(tail) + e.event.head_comment = []byte(node.HeadComment) + e.emit() + + // The tail logic below moves the foot comment of prior keys to the following key, + // since the value for each key may be a nested structure and the foot needs to be + // processed only the entirety of the value is streamed. The last tail is processed + // with the mapping end event. + var tail string + for i := 0; i+1 < len(node.Content); i += 2 { + k := node.Content[i] + foot := k.FootComment + if foot != "" { + kopy := *k + kopy.FootComment = "" + k = &kopy + } + e.node(k, tail) + tail = foot + + v := node.Content[i+1] + e.node(v, "") + } + + yaml_mapping_end_event_initialize(&e.event) + e.event.tail_comment = []byte(tail) + e.event.line_comment = []byte(node.LineComment) + e.event.foot_comment = []byte(node.FootComment) + e.emit() + + case AliasNode: + yaml_alias_event_initialize(&e.event, []byte(node.Value)) + e.event.head_comment = []byte(node.HeadComment) + e.event.line_comment = []byte(node.LineComment) + e.event.foot_comment = []byte(node.FootComment) + e.emit() + + case ScalarNode: + value := node.Value + if !utf8.ValidString(value) { + if stag == binaryTag { + failf("explicitly tagged !!binary data must be base64-encoded") + } + if stag != "" { + failf("cannot marshal invalid UTF-8 data as %s", stag) + } + // It can't be encoded directly as YAML so use a binary tag + // and encode it as base64. + tag = binaryTag + value = encodeBase64(value) + } + + style := yaml_PLAIN_SCALAR_STYLE + switch { + case node.Style&DoubleQuotedStyle != 0: + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + case node.Style&SingleQuotedStyle != 0: + style = yaml_SINGLE_QUOTED_SCALAR_STYLE + case node.Style&LiteralStyle != 0: + style = yaml_LITERAL_SCALAR_STYLE + case node.Style&FoldedStyle != 0: + style = yaml_FOLDED_SCALAR_STYLE + case strings.Contains(value, "\n"): + style = yaml_LITERAL_SCALAR_STYLE + case forceQuoting: + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + + e.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail)) + default: + failf("cannot encode node with unknown kind %d", node.Kind) + } +} diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/parserc.go b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/parserc.go new file mode 100644 index 000000000..ac66fccc0 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/parserc.go @@ -0,0 +1,1249 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// Copyright (c) 2006-2010 Kirill Simonov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package yaml + +import ( + "bytes" +) + +// The parser implements the following grammar: +// +// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END +// implicit_document ::= block_node DOCUMENT-END* +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +// block_node_or_indentless_sequence ::= +// ALIAS +// | properties (block_content | indentless_block_sequence)? +// | block_content +// | indentless_block_sequence +// block_node ::= ALIAS +// | properties block_content? +// | block_content +// flow_node ::= ALIAS +// | properties flow_content? +// | flow_content +// properties ::= TAG ANCHOR? | ANCHOR TAG? +// block_content ::= block_collection | flow_collection | SCALAR +// flow_content ::= flow_collection | SCALAR +// block_collection ::= block_sequence | block_mapping +// flow_collection ::= flow_sequence | flow_mapping +// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END +// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ +// block_mapping ::= BLOCK-MAPPING_START +// ((KEY block_node_or_indentless_sequence?)? +// (VALUE block_node_or_indentless_sequence?)?)* +// BLOCK-END +// flow_sequence ::= FLOW-SEQUENCE-START +// (flow_sequence_entry FLOW-ENTRY)* +// flow_sequence_entry? +// FLOW-SEQUENCE-END +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// flow_mapping ::= FLOW-MAPPING-START +// (flow_mapping_entry FLOW-ENTRY)* +// flow_mapping_entry? +// FLOW-MAPPING-END +// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? + +// Peek the next token in the token queue. +func peek_token(parser *yaml_parser_t) *yaml_token_t { + if parser.token_available || yaml_parser_fetch_more_tokens(parser) { + token := &parser.tokens[parser.tokens_head] + yaml_parser_unfold_comments(parser, token) + return token + } + return nil +} + +// yaml_parser_unfold_comments walks through the comments queue and joins all +// comments behind the position of the provided token into the respective +// top-level comment slices in the parser. +func yaml_parser_unfold_comments(parser *yaml_parser_t, token *yaml_token_t) { + for parser.comments_head < len(parser.comments) && token.start_mark.index >= parser.comments[parser.comments_head].token_mark.index { + comment := &parser.comments[parser.comments_head] + if len(comment.head) > 0 { + if token.typ == yaml_BLOCK_END_TOKEN { + // No heads on ends, so keep comment.head for a follow up token. + break + } + if len(parser.head_comment) > 0 { + parser.head_comment = append(parser.head_comment, '\n') + } + parser.head_comment = append(parser.head_comment, comment.head...) + } + if len(comment.foot) > 0 { + if len(parser.foot_comment) > 0 { + parser.foot_comment = append(parser.foot_comment, '\n') + } + parser.foot_comment = append(parser.foot_comment, comment.foot...) + } + if len(comment.line) > 0 { + if len(parser.line_comment) > 0 { + parser.line_comment = append(parser.line_comment, '\n') + } + parser.line_comment = append(parser.line_comment, comment.line...) + } + *comment = yaml_comment_t{} + parser.comments_head++ + } +} + +// Remove the next token from the queue (must be called after peek_token). +func skip_token(parser *yaml_parser_t) { + parser.token_available = false + parser.tokens_parsed++ + parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN + parser.tokens_head++ +} + +// Get the next event. +func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool { + // Erase the event object. + *event = yaml_event_t{} + + // No events after the end of the stream or error. + if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE { + return true + } + + // Generate the next event. + return yaml_parser_state_machine(parser, event) +} + +// Set parser error. +func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool { + parser.error = yaml_PARSER_ERROR + parser.problem = problem + parser.problem_mark = problem_mark + return false +} + +func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool { + parser.error = yaml_PARSER_ERROR + parser.context = context + parser.context_mark = context_mark + parser.problem = problem + parser.problem_mark = problem_mark + return false +} + +// State dispatcher. +func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool { + //trace("yaml_parser_state_machine", "state:", parser.state.String()) + + switch parser.state { + case yaml_PARSE_STREAM_START_STATE: + return yaml_parser_parse_stream_start(parser, event) + + case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: + return yaml_parser_parse_document_start(parser, event, true) + + case yaml_PARSE_DOCUMENT_START_STATE: + return yaml_parser_parse_document_start(parser, event, false) + + case yaml_PARSE_DOCUMENT_CONTENT_STATE: + return yaml_parser_parse_document_content(parser, event) + + case yaml_PARSE_DOCUMENT_END_STATE: + return yaml_parser_parse_document_end(parser, event) + + case yaml_PARSE_BLOCK_NODE_STATE: + return yaml_parser_parse_node(parser, event, true, false) + + case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: + return yaml_parser_parse_node(parser, event, true, true) + + case yaml_PARSE_FLOW_NODE_STATE: + return yaml_parser_parse_node(parser, event, false, false) + + case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: + return yaml_parser_parse_block_sequence_entry(parser, event, true) + + case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: + return yaml_parser_parse_block_sequence_entry(parser, event, false) + + case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: + return yaml_parser_parse_indentless_sequence_entry(parser, event) + + case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: + return yaml_parser_parse_block_mapping_key(parser, event, true) + + case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: + return yaml_parser_parse_block_mapping_key(parser, event, false) + + case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: + return yaml_parser_parse_block_mapping_value(parser, event) + + case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: + return yaml_parser_parse_flow_sequence_entry(parser, event, true) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: + return yaml_parser_parse_flow_sequence_entry(parser, event, false) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: + return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: + return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: + return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event) + + case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: + return yaml_parser_parse_flow_mapping_key(parser, event, true) + + case yaml_PARSE_FLOW_MAPPING_KEY_STATE: + return yaml_parser_parse_flow_mapping_key(parser, event, false) + + case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: + return yaml_parser_parse_flow_mapping_value(parser, event, false) + + case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: + return yaml_parser_parse_flow_mapping_value(parser, event, true) + + default: + panic("invalid parser state") + } +} + +// Parse the production: +// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END +// ************ +func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_STREAM_START_TOKEN { + return yaml_parser_set_parser_error(parser, "did not find expected ", token.start_mark) + } + parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE + *event = yaml_event_t{ + typ: yaml_STREAM_START_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + encoding: token.encoding, + } + skip_token(parser) + return true +} + +// Parse the productions: +// implicit_document ::= block_node DOCUMENT-END* +// * +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +// ************************* +func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool { + + token := peek_token(parser) + if token == nil { + return false + } + + // Parse extra document end indicators. + if !implicit { + for token.typ == yaml_DOCUMENT_END_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + } + + if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN && + token.typ != yaml_TAG_DIRECTIVE_TOKEN && + token.typ != yaml_DOCUMENT_START_TOKEN && + token.typ != yaml_STREAM_END_TOKEN { + // Parse an implicit document. + if !yaml_parser_process_directives(parser, nil, nil) { + return false + } + parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) + parser.state = yaml_PARSE_BLOCK_NODE_STATE + + var head_comment []byte + if len(parser.head_comment) > 0 { + // [Go] Scan the header comment backwards, and if an empty line is found, break + // the header so the part before the last empty line goes into the + // document header, while the bottom of it goes into a follow up event. + for i := len(parser.head_comment) - 1; i > 0; i-- { + if parser.head_comment[i] == '\n' { + if i == len(parser.head_comment)-1 { + head_comment = parser.head_comment[:i] + parser.head_comment = parser.head_comment[i+1:] + break + } else if parser.head_comment[i-1] == '\n' { + head_comment = parser.head_comment[:i-1] + parser.head_comment = parser.head_comment[i+1:] + break + } + } + } + } + + *event = yaml_event_t{ + typ: yaml_DOCUMENT_START_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + + head_comment: head_comment, + } + + } else if token.typ != yaml_STREAM_END_TOKEN { + // Parse an explicit document. + var version_directive *yaml_version_directive_t + var tag_directives []yaml_tag_directive_t + start_mark := token.start_mark + if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) { + return false + } + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_DOCUMENT_START_TOKEN { + yaml_parser_set_parser_error(parser, + "did not find expected ", token.start_mark) + return false + } + parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) + parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE + end_mark := token.end_mark + + *event = yaml_event_t{ + typ: yaml_DOCUMENT_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + version_directive: version_directive, + tag_directives: tag_directives, + implicit: false, + } + skip_token(parser) + + } else { + // Parse the stream end. + parser.state = yaml_PARSE_END_STATE + *event = yaml_event_t{ + typ: yaml_STREAM_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + skip_token(parser) + } + + return true +} + +// Parse the productions: +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +// *********** +// +func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_VERSION_DIRECTIVE_TOKEN || + token.typ == yaml_TAG_DIRECTIVE_TOKEN || + token.typ == yaml_DOCUMENT_START_TOKEN || + token.typ == yaml_DOCUMENT_END_TOKEN || + token.typ == yaml_STREAM_END_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + return yaml_parser_process_empty_scalar(parser, event, + token.start_mark) + } + return yaml_parser_parse_node(parser, event, true, false) +} + +// Parse the productions: +// implicit_document ::= block_node DOCUMENT-END* +// ************* +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +// +func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + + start_mark := token.start_mark + end_mark := token.start_mark + + implicit := true + if token.typ == yaml_DOCUMENT_END_TOKEN { + end_mark = token.end_mark + skip_token(parser) + implicit = false + } + + parser.tag_directives = parser.tag_directives[:0] + + parser.state = yaml_PARSE_DOCUMENT_START_STATE + *event = yaml_event_t{ + typ: yaml_DOCUMENT_END_EVENT, + start_mark: start_mark, + end_mark: end_mark, + implicit: implicit, + } + yaml_parser_set_event_comments(parser, event) + if len(event.head_comment) > 0 && len(event.foot_comment) == 0 { + event.foot_comment = event.head_comment + event.head_comment = nil + } + return true +} + +func yaml_parser_set_event_comments(parser *yaml_parser_t, event *yaml_event_t) { + event.head_comment = parser.head_comment + event.line_comment = parser.line_comment + event.foot_comment = parser.foot_comment + parser.head_comment = nil + parser.line_comment = nil + parser.foot_comment = nil + parser.tail_comment = nil + parser.stem_comment = nil +} + +// Parse the productions: +// block_node_or_indentless_sequence ::= +// ALIAS +// ***** +// | properties (block_content | indentless_block_sequence)? +// ********** * +// | block_content | indentless_block_sequence +// * +// block_node ::= ALIAS +// ***** +// | properties block_content? +// ********** * +// | block_content +// * +// flow_node ::= ALIAS +// ***** +// | properties flow_content? +// ********** * +// | flow_content +// * +// properties ::= TAG ANCHOR? | ANCHOR TAG? +// ************************* +// block_content ::= block_collection | flow_collection | SCALAR +// ****** +// flow_content ::= flow_collection | SCALAR +// ****** +func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool { + //defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)() + + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_ALIAS_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + *event = yaml_event_t{ + typ: yaml_ALIAS_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + anchor: token.value, + } + yaml_parser_set_event_comments(parser, event) + skip_token(parser) + return true + } + + start_mark := token.start_mark + end_mark := token.start_mark + + var tag_token bool + var tag_handle, tag_suffix, anchor []byte + var tag_mark yaml_mark_t + if token.typ == yaml_ANCHOR_TOKEN { + anchor = token.value + start_mark = token.start_mark + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_TAG_TOKEN { + tag_token = true + tag_handle = token.value + tag_suffix = token.suffix + tag_mark = token.start_mark + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + } else if token.typ == yaml_TAG_TOKEN { + tag_token = true + tag_handle = token.value + tag_suffix = token.suffix + start_mark = token.start_mark + tag_mark = token.start_mark + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_ANCHOR_TOKEN { + anchor = token.value + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + } + + var tag []byte + if tag_token { + if len(tag_handle) == 0 { + tag = tag_suffix + tag_suffix = nil + } else { + for i := range parser.tag_directives { + if bytes.Equal(parser.tag_directives[i].handle, tag_handle) { + tag = append([]byte(nil), parser.tag_directives[i].prefix...) + tag = append(tag, tag_suffix...) + break + } + } + if len(tag) == 0 { + yaml_parser_set_parser_error_context(parser, + "while parsing a node", start_mark, + "found undefined tag handle", tag_mark) + return false + } + } + } + + implicit := len(tag) == 0 + if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), + } + return true + } + if token.typ == yaml_SCALAR_TOKEN { + var plain_implicit, quoted_implicit bool + end_mark = token.end_mark + if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') { + plain_implicit = true + } else if len(tag) == 0 { + quoted_implicit = true + } + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + value: token.value, + implicit: plain_implicit, + quoted_implicit: quoted_implicit, + style: yaml_style_t(token.style), + } + yaml_parser_set_event_comments(parser, event) + skip_token(parser) + return true + } + if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN { + // [Go] Some of the events below can be merged as they differ only on style. + end_mark = token.end_mark + parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_FLOW_SEQUENCE_STYLE), + } + yaml_parser_set_event_comments(parser, event) + return true + } + if token.typ == yaml_FLOW_MAPPING_START_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), + } + yaml_parser_set_event_comments(parser, event) + return true + } + if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), + } + if parser.stem_comment != nil { + event.head_comment = parser.stem_comment + parser.stem_comment = nil + } + return true + } + if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE), + } + if parser.stem_comment != nil { + event.head_comment = parser.stem_comment + parser.stem_comment = nil + } + return true + } + if len(anchor) > 0 || len(tag) > 0 { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + quoted_implicit: false, + style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), + } + return true + } + + context := "while parsing a flow node" + if block { + context = "while parsing a block node" + } + yaml_parser_set_parser_error_context(parser, context, start_mark, + "did not find expected node content", token.start_mark) + return false +} + +// Parse the productions: +// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END +// ******************** *********** * ********* +// +func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_BLOCK_ENTRY_TOKEN { + mark := token.end_mark + prior_head_len := len(parser.head_comment) + skip_token(parser) + yaml_parser_split_stem_comment(parser, prior_head_len) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE) + return yaml_parser_parse_node(parser, event, true, false) + } else { + parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + } + if token.typ == yaml_BLOCK_END_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + + skip_token(parser) + return true + } + + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a block collection", context_mark, + "did not find expected '-' indicator", token.start_mark) +} + +// Parse the productions: +// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ +// *********** * +func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_BLOCK_ENTRY_TOKEN { + mark := token.end_mark + prior_head_len := len(parser.head_comment) + skip_token(parser) + yaml_parser_split_stem_comment(parser, prior_head_len) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_BLOCK_ENTRY_TOKEN && + token.typ != yaml_KEY_TOKEN && + token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE) + return yaml_parser_parse_node(parser, event, true, false) + } + parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + start_mark: token.start_mark, + end_mark: token.start_mark, // [Go] Shouldn't this be token.end_mark? + } + return true +} + +// Split stem comment from head comment. +// +// When a sequence or map is found under a sequence entry, the former head comment +// is assigned to the underlying sequence or map as a whole, not the individual +// sequence or map entry as would be expected otherwise. To handle this case the +// previous head comment is moved aside as the stem comment. +func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) { + if stem_len == 0 { + return + } + + token := peek_token(parser) + if token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN { + return + } + + parser.stem_comment = parser.head_comment[:stem_len] + if len(parser.head_comment) == stem_len { + parser.head_comment = nil + } else { + // Copy suffix to prevent very strange bugs if someone ever appends + // further bytes to the prefix in the stem_comment slice above. + parser.head_comment = append([]byte(nil), parser.head_comment[stem_len+1:]...) + } +} + +// Parse the productions: +// block_mapping ::= BLOCK-MAPPING_START +// ******************* +// ((KEY block_node_or_indentless_sequence?)? +// *** * +// (VALUE block_node_or_indentless_sequence?)?)* +// +// BLOCK-END +// ********* +// +func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + + token := peek_token(parser) + if token == nil { + return false + } + + // [Go] A tail comment was left from the prior mapping value processed. Emit an event + // as it needs to be processed with that value and not the following key. + if len(parser.tail_comment) > 0 { + *event = yaml_event_t{ + typ: yaml_TAIL_COMMENT_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + foot_comment: parser.tail_comment, + } + parser.tail_comment = nil + return true + } + + if token.typ == yaml_KEY_TOKEN { + mark := token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_KEY_TOKEN && + token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE) + return yaml_parser_parse_node(parser, event, true, true) + } else { + parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + } else if token.typ == yaml_BLOCK_END_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + yaml_parser_set_event_comments(parser, event) + skip_token(parser) + return true + } + + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a block mapping", context_mark, + "did not find expected key", token.start_mark) +} + +// Parse the productions: +// block_mapping ::= BLOCK-MAPPING_START +// +// ((KEY block_node_or_indentless_sequence?)? +// +// (VALUE block_node_or_indentless_sequence?)?)* +// ***** * +// BLOCK-END +// +// +func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_VALUE_TOKEN { + mark := token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_KEY_TOKEN && + token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE) + return yaml_parser_parse_node(parser, event, true, true) + } + parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) +} + +// Parse the productions: +// flow_sequence ::= FLOW-SEQUENCE-START +// ******************* +// (flow_sequence_entry FLOW-ENTRY)* +// * ********** +// flow_sequence_entry? +// * +// FLOW-SEQUENCE-END +// ***************** +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// * +// +func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + if !first { + if token.typ == yaml_FLOW_ENTRY_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } else { + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a flow sequence", context_mark, + "did not find expected ',' or ']'", token.start_mark) + } + } + + if token.typ == yaml_KEY_TOKEN { + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + implicit: true, + style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), + } + skip_token(parser) + return true + } else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + yaml_parser_set_event_comments(parser, event) + + skip_token(parser) + return true +} + +// +// Parse the productions: +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// *** * +// +func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_FLOW_ENTRY_TOKEN && + token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + mark := token.end_mark + skip_token(parser) + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) +} + +// Parse the productions: +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// ***** * +// +func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_VALUE_TOKEN { + skip_token(parser) + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) +} + +// Parse the productions: +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// * +// +func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + start_mark: token.start_mark, + end_mark: token.start_mark, // [Go] Shouldn't this be end_mark? + } + return true +} + +// Parse the productions: +// flow_mapping ::= FLOW-MAPPING-START +// ****************** +// (flow_mapping_entry FLOW-ENTRY)* +// * ********** +// flow_mapping_entry? +// ****************** +// FLOW-MAPPING-END +// **************** +// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// * *** * +// +func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ != yaml_FLOW_MAPPING_END_TOKEN { + if !first { + if token.typ == yaml_FLOW_ENTRY_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } else { + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a flow mapping", context_mark, + "did not find expected ',' or '}'", token.start_mark) + } + } + + if token.typ == yaml_KEY_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_FLOW_ENTRY_TOKEN && + token.typ != yaml_FLOW_MAPPING_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } else { + parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) + } + } else if token.typ != yaml_FLOW_MAPPING_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + yaml_parser_set_event_comments(parser, event) + skip_token(parser) + return true +} + +// Parse the productions: +// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// * ***** * +// +func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool { + token := peek_token(parser) + if token == nil { + return false + } + if empty { + parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) + } + if token.typ == yaml_VALUE_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) +} + +// Generate an empty scalar event. +func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool { + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + start_mark: mark, + end_mark: mark, + value: nil, // Empty + implicit: true, + style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), + } + return true +} + +var default_tag_directives = []yaml_tag_directive_t{ + {[]byte("!"), []byte("!")}, + {[]byte("!!"), []byte("tag:yaml.org,2002:")}, +} + +// Parse directives. +func yaml_parser_process_directives(parser *yaml_parser_t, + version_directive_ref **yaml_version_directive_t, + tag_directives_ref *[]yaml_tag_directive_t) bool { + + var version_directive *yaml_version_directive_t + var tag_directives []yaml_tag_directive_t + + token := peek_token(parser) + if token == nil { + return false + } + + for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN { + if token.typ == yaml_VERSION_DIRECTIVE_TOKEN { + if version_directive != nil { + yaml_parser_set_parser_error(parser, + "found duplicate %YAML directive", token.start_mark) + return false + } + if token.major != 1 || token.minor != 1 { + yaml_parser_set_parser_error(parser, + "found incompatible YAML document", token.start_mark) + return false + } + version_directive = &yaml_version_directive_t{ + major: token.major, + minor: token.minor, + } + } else if token.typ == yaml_TAG_DIRECTIVE_TOKEN { + value := yaml_tag_directive_t{ + handle: token.value, + prefix: token.prefix, + } + if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) { + return false + } + tag_directives = append(tag_directives, value) + } + + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + + for i := range default_tag_directives { + if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) { + return false + } + } + + if version_directive_ref != nil { + *version_directive_ref = version_directive + } + if tag_directives_ref != nil { + *tag_directives_ref = tag_directives + } + return true +} + +// Append a tag directive to the directives stack. +func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool { + for i := range parser.tag_directives { + if bytes.Equal(value.handle, parser.tag_directives[i].handle) { + if allow_duplicates { + return true + } + return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark) + } + } + + // [Go] I suspect the copy is unnecessary. This was likely done + // because there was no way to track ownership of the data. + value_copy := yaml_tag_directive_t{ + handle: make([]byte, len(value.handle)), + prefix: make([]byte, len(value.prefix)), + } + copy(value_copy.handle, value.handle) + copy(value_copy.prefix, value.prefix) + parser.tag_directives = append(parser.tag_directives, value_copy) + return true +} diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/readerc.go b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/readerc.go new file mode 100644 index 000000000..b7de0a89c --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/readerc.go @@ -0,0 +1,434 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// Copyright (c) 2006-2010 Kirill Simonov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package yaml + +import ( + "io" +) + +// Set the reader error and return 0. +func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool { + parser.error = yaml_READER_ERROR + parser.problem = problem + parser.problem_offset = offset + parser.problem_value = value + return false +} + +// Byte order marks. +const ( + bom_UTF8 = "\xef\xbb\xbf" + bom_UTF16LE = "\xff\xfe" + bom_UTF16BE = "\xfe\xff" +) + +// Determine the input stream encoding by checking the BOM symbol. If no BOM is +// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure. +func yaml_parser_determine_encoding(parser *yaml_parser_t) bool { + // Ensure that we had enough bytes in the raw buffer. + for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 { + if !yaml_parser_update_raw_buffer(parser) { + return false + } + } + + // Determine the encoding. + buf := parser.raw_buffer + pos := parser.raw_buffer_pos + avail := len(buf) - pos + if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] { + parser.encoding = yaml_UTF16LE_ENCODING + parser.raw_buffer_pos += 2 + parser.offset += 2 + } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] { + parser.encoding = yaml_UTF16BE_ENCODING + parser.raw_buffer_pos += 2 + parser.offset += 2 + } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] { + parser.encoding = yaml_UTF8_ENCODING + parser.raw_buffer_pos += 3 + parser.offset += 3 + } else { + parser.encoding = yaml_UTF8_ENCODING + } + return true +} + +// Update the raw buffer. +func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool { + size_read := 0 + + // Return if the raw buffer is full. + if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) { + return true + } + + // Return on EOF. + if parser.eof { + return true + } + + // Move the remaining bytes in the raw buffer to the beginning. + if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) { + copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:]) + } + parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos] + parser.raw_buffer_pos = 0 + + // Call the read handler to fill the buffer. + size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)]) + parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read] + if err == io.EOF { + parser.eof = true + } else if err != nil { + return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1) + } + return true +} + +// Ensure that the buffer contains at least `length` characters. +// Return true on success, false on failure. +// +// The length is supposed to be significantly less that the buffer size. +func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool { + if parser.read_handler == nil { + panic("read handler must be set") + } + + // [Go] This function was changed to guarantee the requested length size at EOF. + // The fact we need to do this is pretty awful, but the description above implies + // for that to be the case, and there are tests + + // If the EOF flag is set and the raw buffer is empty, do nothing. + if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { + // [Go] ACTUALLY! Read the documentation of this function above. + // This is just broken. To return true, we need to have the + // given length in the buffer. Not doing that means every single + // check that calls this function to make sure the buffer has a + // given length is Go) panicking; or C) accessing invalid memory. + //return true + } + + // Return if the buffer contains enough characters. + if parser.unread >= length { + return true + } + + // Determine the input encoding if it is not known yet. + if parser.encoding == yaml_ANY_ENCODING { + if !yaml_parser_determine_encoding(parser) { + return false + } + } + + // Move the unread characters to the beginning of the buffer. + buffer_len := len(parser.buffer) + if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len { + copy(parser.buffer, parser.buffer[parser.buffer_pos:]) + buffer_len -= parser.buffer_pos + parser.buffer_pos = 0 + } else if parser.buffer_pos == buffer_len { + buffer_len = 0 + parser.buffer_pos = 0 + } + + // Open the whole buffer for writing, and cut it before returning. + parser.buffer = parser.buffer[:cap(parser.buffer)] + + // Fill the buffer until it has enough characters. + first := true + for parser.unread < length { + + // Fill the raw buffer if necessary. + if !first || parser.raw_buffer_pos == len(parser.raw_buffer) { + if !yaml_parser_update_raw_buffer(parser) { + parser.buffer = parser.buffer[:buffer_len] + return false + } + } + first = false + + // Decode the raw buffer. + inner: + for parser.raw_buffer_pos != len(parser.raw_buffer) { + var value rune + var width int + + raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos + + // Decode the next character. + switch parser.encoding { + case yaml_UTF8_ENCODING: + // Decode a UTF-8 character. Check RFC 3629 + // (http://www.ietf.org/rfc/rfc3629.txt) for more details. + // + // The following table (taken from the RFC) is used for + // decoding. + // + // Char. number range | UTF-8 octet sequence + // (hexadecimal) | (binary) + // --------------------+------------------------------------ + // 0000 0000-0000 007F | 0xxxxxxx + // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx + // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx + // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + // + // Additionally, the characters in the range 0xD800-0xDFFF + // are prohibited as they are reserved for use with UTF-16 + // surrogate pairs. + + // Determine the length of the UTF-8 sequence. + octet := parser.raw_buffer[parser.raw_buffer_pos] + switch { + case octet&0x80 == 0x00: + width = 1 + case octet&0xE0 == 0xC0: + width = 2 + case octet&0xF0 == 0xE0: + width = 3 + case octet&0xF8 == 0xF0: + width = 4 + default: + // The leading octet is invalid. + return yaml_parser_set_reader_error(parser, + "invalid leading UTF-8 octet", + parser.offset, int(octet)) + } + + // Check if the raw buffer contains an incomplete character. + if width > raw_unread { + if parser.eof { + return yaml_parser_set_reader_error(parser, + "incomplete UTF-8 octet sequence", + parser.offset, -1) + } + break inner + } + + // Decode the leading octet. + switch { + case octet&0x80 == 0x00: + value = rune(octet & 0x7F) + case octet&0xE0 == 0xC0: + value = rune(octet & 0x1F) + case octet&0xF0 == 0xE0: + value = rune(octet & 0x0F) + case octet&0xF8 == 0xF0: + value = rune(octet & 0x07) + default: + value = 0 + } + + // Check and decode the trailing octets. + for k := 1; k < width; k++ { + octet = parser.raw_buffer[parser.raw_buffer_pos+k] + + // Check if the octet is valid. + if (octet & 0xC0) != 0x80 { + return yaml_parser_set_reader_error(parser, + "invalid trailing UTF-8 octet", + parser.offset+k, int(octet)) + } + + // Decode the octet. + value = (value << 6) + rune(octet&0x3F) + } + + // Check the length of the sequence against the value. + switch { + case width == 1: + case width == 2 && value >= 0x80: + case width == 3 && value >= 0x800: + case width == 4 && value >= 0x10000: + default: + return yaml_parser_set_reader_error(parser, + "invalid length of a UTF-8 sequence", + parser.offset, -1) + } + + // Check the range of the value. + if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF { + return yaml_parser_set_reader_error(parser, + "invalid Unicode character", + parser.offset, int(value)) + } + + case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING: + var low, high int + if parser.encoding == yaml_UTF16LE_ENCODING { + low, high = 0, 1 + } else { + low, high = 1, 0 + } + + // The UTF-16 encoding is not as simple as one might + // naively think. Check RFC 2781 + // (http://www.ietf.org/rfc/rfc2781.txt). + // + // Normally, two subsequent bytes describe a Unicode + // character. However a special technique (called a + // surrogate pair) is used for specifying character + // values larger than 0xFFFF. + // + // A surrogate pair consists of two pseudo-characters: + // high surrogate area (0xD800-0xDBFF) + // low surrogate area (0xDC00-0xDFFF) + // + // The following formulas are used for decoding + // and encoding characters using surrogate pairs: + // + // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF) + // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF) + // W1 = 110110yyyyyyyyyy + // W2 = 110111xxxxxxxxxx + // + // where U is the character value, W1 is the high surrogate + // area, W2 is the low surrogate area. + + // Check for incomplete UTF-16 character. + if raw_unread < 2 { + if parser.eof { + return yaml_parser_set_reader_error(parser, + "incomplete UTF-16 character", + parser.offset, -1) + } + break inner + } + + // Get the character. + value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) + + (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8) + + // Check for unexpected low surrogate area. + if value&0xFC00 == 0xDC00 { + return yaml_parser_set_reader_error(parser, + "unexpected low surrogate area", + parser.offset, int(value)) + } + + // Check for a high surrogate area. + if value&0xFC00 == 0xD800 { + width = 4 + + // Check for incomplete surrogate pair. + if raw_unread < 4 { + if parser.eof { + return yaml_parser_set_reader_error(parser, + "incomplete UTF-16 surrogate pair", + parser.offset, -1) + } + break inner + } + + // Get the next character. + value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) + + (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8) + + // Check for a low surrogate area. + if value2&0xFC00 != 0xDC00 { + return yaml_parser_set_reader_error(parser, + "expected low surrogate area", + parser.offset+2, int(value2)) + } + + // Generate the value of the surrogate pair. + value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF) + } else { + width = 2 + } + + default: + panic("impossible") + } + + // Check if the character is in the allowed range: + // #x9 | #xA | #xD | [#x20-#x7E] (8 bit) + // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit) + // | [#x10000-#x10FFFF] (32 bit) + switch { + case value == 0x09: + case value == 0x0A: + case value == 0x0D: + case value >= 0x20 && value <= 0x7E: + case value == 0x85: + case value >= 0xA0 && value <= 0xD7FF: + case value >= 0xE000 && value <= 0xFFFD: + case value >= 0x10000 && value <= 0x10FFFF: + default: + return yaml_parser_set_reader_error(parser, + "control characters are not allowed", + parser.offset, int(value)) + } + + // Move the raw pointers. + parser.raw_buffer_pos += width + parser.offset += width + + // Finally put the character into the buffer. + if value <= 0x7F { + // 0000 0000-0000 007F . 0xxxxxxx + parser.buffer[buffer_len+0] = byte(value) + buffer_len += 1 + } else if value <= 0x7FF { + // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx + parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6)) + parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F)) + buffer_len += 2 + } else if value <= 0xFFFF { + // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx + parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12)) + parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F)) + parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F)) + buffer_len += 3 + } else { + // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18)) + parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F)) + parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F)) + parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F)) + buffer_len += 4 + } + + parser.unread++ + } + + // On EOF, put NUL into the buffer and return. + if parser.eof { + parser.buffer[buffer_len] = 0 + buffer_len++ + parser.unread++ + break + } + } + // [Go] Read the documentation of this function above. To return true, + // we need to have the given length in the buffer. Not doing that means + // every single check that calls this function to make sure the buffer + // has a given length is Go) panicking; or C) accessing invalid memory. + // This happens here due to the EOF above breaking early. + for buffer_len < length { + parser.buffer[buffer_len] = 0 + buffer_len++ + } + parser.buffer = parser.buffer[:buffer_len] + return true +} diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/resolve.go b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/resolve.go new file mode 100644 index 000000000..64ae88805 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/resolve.go @@ -0,0 +1,326 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package yaml + +import ( + "encoding/base64" + "math" + "regexp" + "strconv" + "strings" + "time" +) + +type resolveMapItem struct { + value interface{} + tag string +} + +var resolveTable = make([]byte, 256) +var resolveMap = make(map[string]resolveMapItem) + +func init() { + t := resolveTable + t[int('+')] = 'S' // Sign + t[int('-')] = 'S' + for _, c := range "0123456789" { + t[int(c)] = 'D' // Digit + } + for _, c := range "yYnNtTfFoO~" { + t[int(c)] = 'M' // In map + } + t[int('.')] = '.' // Float (potentially in map) + + var resolveMapList = []struct { + v interface{} + tag string + l []string + }{ + {true, boolTag, []string{"true", "True", "TRUE"}}, + {false, boolTag, []string{"false", "False", "FALSE"}}, + {nil, nullTag, []string{"", "~", "null", "Null", "NULL"}}, + {math.NaN(), floatTag, []string{".nan", ".NaN", ".NAN"}}, + {math.Inf(+1), floatTag, []string{".inf", ".Inf", ".INF"}}, + {math.Inf(+1), floatTag, []string{"+.inf", "+.Inf", "+.INF"}}, + {math.Inf(-1), floatTag, []string{"-.inf", "-.Inf", "-.INF"}}, + {"<<", mergeTag, []string{"<<"}}, + } + + m := resolveMap + for _, item := range resolveMapList { + for _, s := range item.l { + m[s] = resolveMapItem{item.v, item.tag} + } + } +} + +const ( + nullTag = "!!null" + boolTag = "!!bool" + strTag = "!!str" + intTag = "!!int" + floatTag = "!!float" + timestampTag = "!!timestamp" + seqTag = "!!seq" + mapTag = "!!map" + binaryTag = "!!binary" + mergeTag = "!!merge" +) + +var longTags = make(map[string]string) +var shortTags = make(map[string]string) + +func init() { + for _, stag := range []string{nullTag, boolTag, strTag, intTag, floatTag, timestampTag, seqTag, mapTag, binaryTag, mergeTag} { + ltag := longTag(stag) + longTags[stag] = ltag + shortTags[ltag] = stag + } +} + +const longTagPrefix = "tag:yaml.org,2002:" + +func shortTag(tag string) string { + if strings.HasPrefix(tag, longTagPrefix) { + if stag, ok := shortTags[tag]; ok { + return stag + } + return "!!" + tag[len(longTagPrefix):] + } + return tag +} + +func longTag(tag string) string { + if strings.HasPrefix(tag, "!!") { + if ltag, ok := longTags[tag]; ok { + return ltag + } + return longTagPrefix + tag[2:] + } + return tag +} + +func resolvableTag(tag string) bool { + switch tag { + case "", strTag, boolTag, intTag, floatTag, nullTag, timestampTag: + return true + } + return false +} + +var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`) + +func resolve(tag string, in string) (rtag string, out interface{}) { + tag = shortTag(tag) + if !resolvableTag(tag) { + return tag, in + } + + defer func() { + switch tag { + case "", rtag, strTag, binaryTag: + return + case floatTag: + if rtag == intTag { + switch v := out.(type) { + case int64: + rtag = floatTag + out = float64(v) + return + case int: + rtag = floatTag + out = float64(v) + return + } + } + } + failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)) + }() + + // Any data is accepted as a !!str or !!binary. + // Otherwise, the prefix is enough of a hint about what it might be. + hint := byte('N') + if in != "" { + hint = resolveTable[in[0]] + } + if hint != 0 && tag != strTag && tag != binaryTag { + // Handle things we can lookup in a map. + if item, ok := resolveMap[in]; ok { + return item.tag, item.value + } + + // Base 60 floats are a bad idea, were dropped in YAML 1.2, and + // are purposefully unsupported here. They're still quoted on + // the way out for compatibility with other parser, though. + + switch hint { + case 'M': + // We've already checked the map above. + + case '.': + // Not in the map, so maybe a normal float. + floatv, err := strconv.ParseFloat(in, 64) + if err == nil { + return floatTag, floatv + } + + case 'D', 'S': + // Int, float, or timestamp. + // Only try values as a timestamp if the value is unquoted or there's an explicit + // !!timestamp tag. + if tag == "" || tag == timestampTag { + t, ok := parseTimestamp(in) + if ok { + return timestampTag, t + } + } + + plain := strings.Replace(in, "_", "", -1) + intv, err := strconv.ParseInt(plain, 0, 64) + if err == nil { + if intv == int64(int(intv)) { + return intTag, int(intv) + } else { + return intTag, intv + } + } + uintv, err := strconv.ParseUint(plain, 0, 64) + if err == nil { + return intTag, uintv + } + if yamlStyleFloat.MatchString(plain) { + floatv, err := strconv.ParseFloat(plain, 64) + if err == nil { + return floatTag, floatv + } + } + if strings.HasPrefix(plain, "0b") { + intv, err := strconv.ParseInt(plain[2:], 2, 64) + if err == nil { + if intv == int64(int(intv)) { + return intTag, int(intv) + } else { + return intTag, intv + } + } + uintv, err := strconv.ParseUint(plain[2:], 2, 64) + if err == nil { + return intTag, uintv + } + } else if strings.HasPrefix(plain, "-0b") { + intv, err := strconv.ParseInt("-"+plain[3:], 2, 64) + if err == nil { + if true || intv == int64(int(intv)) { + return intTag, int(intv) + } else { + return intTag, intv + } + } + } + // Octals as introduced in version 1.2 of the spec. + // Octals from the 1.1 spec, spelled as 0777, are still + // decoded by default in v3 as well for compatibility. + // May be dropped in v4 depending on how usage evolves. + if strings.HasPrefix(plain, "0o") { + intv, err := strconv.ParseInt(plain[2:], 8, 64) + if err == nil { + if intv == int64(int(intv)) { + return intTag, int(intv) + } else { + return intTag, intv + } + } + uintv, err := strconv.ParseUint(plain[2:], 8, 64) + if err == nil { + return intTag, uintv + } + } else if strings.HasPrefix(plain, "-0o") { + intv, err := strconv.ParseInt("-"+plain[3:], 8, 64) + if err == nil { + if true || intv == int64(int(intv)) { + return intTag, int(intv) + } else { + return intTag, intv + } + } + } + default: + panic("internal error: missing handler for resolver table: " + string(rune(hint)) + " (with " + in + ")") + } + } + return strTag, in +} + +// encodeBase64 encodes s as base64 that is broken up into multiple lines +// as appropriate for the resulting length. +func encodeBase64(s string) string { + const lineLen = 70 + encLen := base64.StdEncoding.EncodedLen(len(s)) + lines := encLen/lineLen + 1 + buf := make([]byte, encLen*2+lines) + in := buf[0:encLen] + out := buf[encLen:] + base64.StdEncoding.Encode(in, []byte(s)) + k := 0 + for i := 0; i < len(in); i += lineLen { + j := i + lineLen + if j > len(in) { + j = len(in) + } + k += copy(out[k:], in[i:j]) + if lines > 1 { + out[k] = '\n' + k++ + } + } + return string(out[:k]) +} + +// This is a subset of the formats allowed by the regular expression +// defined at http://yaml.org/type/timestamp.html. +var allowedTimestampFormats = []string{ + "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields. + "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t". + "2006-1-2 15:4:5.999999999", // space separated with no time zone + "2006-1-2", // date only + // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5" + // from the set of examples. +} + +// parseTimestamp parses s as a timestamp string and +// returns the timestamp and reports whether it succeeded. +// Timestamp formats are defined at http://yaml.org/type/timestamp.html +func parseTimestamp(s string) (time.Time, bool) { + // TODO write code to check all the formats supported by + // http://yaml.org/type/timestamp.html instead of using time.Parse. + + // Quick check: all date formats start with YYYY-. + i := 0 + for ; i < len(s); i++ { + if c := s[i]; c < '0' || c > '9' { + break + } + } + if i != 4 || i == len(s) || s[i] != '-' { + return time.Time{}, false + } + for _, format := range allowedTimestampFormats { + if t, err := time.Parse(format, s); err == nil { + return t, true + } + } + return time.Time{}, false +} diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/scannerc.go b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/scannerc.go new file mode 100644 index 000000000..ca0070108 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/scannerc.go @@ -0,0 +1,3038 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// Copyright (c) 2006-2010 Kirill Simonov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package yaml + +import ( + "bytes" + "fmt" +) + +// Introduction +// ************ +// +// The following notes assume that you are familiar with the YAML specification +// (http://yaml.org/spec/1.2/spec.html). We mostly follow it, although in +// some cases we are less restrictive that it requires. +// +// The process of transforming a YAML stream into a sequence of events is +// divided on two steps: Scanning and Parsing. +// +// The Scanner transforms the input stream into a sequence of tokens, while the +// parser transform the sequence of tokens produced by the Scanner into a +// sequence of parsing events. +// +// The Scanner is rather clever and complicated. The Parser, on the contrary, +// is a straightforward implementation of a recursive-descendant parser (or, +// LL(1) parser, as it is usually called). +// +// Actually there are two issues of Scanning that might be called "clever", the +// rest is quite straightforward. The issues are "block collection start" and +// "simple keys". Both issues are explained below in details. +// +// Here the Scanning step is explained and implemented. We start with the list +// of all the tokens produced by the Scanner together with short descriptions. +// +// Now, tokens: +// +// STREAM-START(encoding) # The stream start. +// STREAM-END # The stream end. +// VERSION-DIRECTIVE(major,minor) # The '%YAML' directive. +// TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive. +// DOCUMENT-START # '---' +// DOCUMENT-END # '...' +// BLOCK-SEQUENCE-START # Indentation increase denoting a block +// BLOCK-MAPPING-START # sequence or a block mapping. +// BLOCK-END # Indentation decrease. +// FLOW-SEQUENCE-START # '[' +// FLOW-SEQUENCE-END # ']' +// BLOCK-SEQUENCE-START # '{' +// BLOCK-SEQUENCE-END # '}' +// BLOCK-ENTRY # '-' +// FLOW-ENTRY # ',' +// KEY # '?' or nothing (simple keys). +// VALUE # ':' +// ALIAS(anchor) # '*anchor' +// ANCHOR(anchor) # '&anchor' +// TAG(handle,suffix) # '!handle!suffix' +// SCALAR(value,style) # A scalar. +// +// The following two tokens are "virtual" tokens denoting the beginning and the +// end of the stream: +// +// STREAM-START(encoding) +// STREAM-END +// +// We pass the information about the input stream encoding with the +// STREAM-START token. +// +// The next two tokens are responsible for tags: +// +// VERSION-DIRECTIVE(major,minor) +// TAG-DIRECTIVE(handle,prefix) +// +// Example: +// +// %YAML 1.1 +// %TAG ! !foo +// %TAG !yaml! tag:yaml.org,2002: +// --- +// +// The correspoding sequence of tokens: +// +// STREAM-START(utf-8) +// VERSION-DIRECTIVE(1,1) +// TAG-DIRECTIVE("!","!foo") +// TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:") +// DOCUMENT-START +// STREAM-END +// +// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole +// line. +// +// The document start and end indicators are represented by: +// +// DOCUMENT-START +// DOCUMENT-END +// +// Note that if a YAML stream contains an implicit document (without '---' +// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be +// produced. +// +// In the following examples, we present whole documents together with the +// produced tokens. +// +// 1. An implicit document: +// +// 'a scalar' +// +// Tokens: +// +// STREAM-START(utf-8) +// SCALAR("a scalar",single-quoted) +// STREAM-END +// +// 2. An explicit document: +// +// --- +// 'a scalar' +// ... +// +// Tokens: +// +// STREAM-START(utf-8) +// DOCUMENT-START +// SCALAR("a scalar",single-quoted) +// DOCUMENT-END +// STREAM-END +// +// 3. Several documents in a stream: +// +// 'a scalar' +// --- +// 'another scalar' +// --- +// 'yet another scalar' +// +// Tokens: +// +// STREAM-START(utf-8) +// SCALAR("a scalar",single-quoted) +// DOCUMENT-START +// SCALAR("another scalar",single-quoted) +// DOCUMENT-START +// SCALAR("yet another scalar",single-quoted) +// STREAM-END +// +// We have already introduced the SCALAR token above. The following tokens are +// used to describe aliases, anchors, tag, and scalars: +// +// ALIAS(anchor) +// ANCHOR(anchor) +// TAG(handle,suffix) +// SCALAR(value,style) +// +// The following series of examples illustrate the usage of these tokens: +// +// 1. A recursive sequence: +// +// &A [ *A ] +// +// Tokens: +// +// STREAM-START(utf-8) +// ANCHOR("A") +// FLOW-SEQUENCE-START +// ALIAS("A") +// FLOW-SEQUENCE-END +// STREAM-END +// +// 2. A tagged scalar: +// +// !!float "3.14" # A good approximation. +// +// Tokens: +// +// STREAM-START(utf-8) +// TAG("!!","float") +// SCALAR("3.14",double-quoted) +// STREAM-END +// +// 3. Various scalar styles: +// +// --- # Implicit empty plain scalars do not produce tokens. +// --- a plain scalar +// --- 'a single-quoted scalar' +// --- "a double-quoted scalar" +// --- |- +// a literal scalar +// --- >- +// a folded +// scalar +// +// Tokens: +// +// STREAM-START(utf-8) +// DOCUMENT-START +// DOCUMENT-START +// SCALAR("a plain scalar",plain) +// DOCUMENT-START +// SCALAR("a single-quoted scalar",single-quoted) +// DOCUMENT-START +// SCALAR("a double-quoted scalar",double-quoted) +// DOCUMENT-START +// SCALAR("a literal scalar",literal) +// DOCUMENT-START +// SCALAR("a folded scalar",folded) +// STREAM-END +// +// Now it's time to review collection-related tokens. We will start with +// flow collections: +// +// FLOW-SEQUENCE-START +// FLOW-SEQUENCE-END +// FLOW-MAPPING-START +// FLOW-MAPPING-END +// FLOW-ENTRY +// KEY +// VALUE +// +// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and +// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}' +// correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the +// indicators '?' and ':', which are used for denoting mapping keys and values, +// are represented by the KEY and VALUE tokens. +// +// The following examples show flow collections: +// +// 1. A flow sequence: +// +// [item 1, item 2, item 3] +// +// Tokens: +// +// STREAM-START(utf-8) +// FLOW-SEQUENCE-START +// SCALAR("item 1",plain) +// FLOW-ENTRY +// SCALAR("item 2",plain) +// FLOW-ENTRY +// SCALAR("item 3",plain) +// FLOW-SEQUENCE-END +// STREAM-END +// +// 2. A flow mapping: +// +// { +// a simple key: a value, # Note that the KEY token is produced. +// ? a complex key: another value, +// } +// +// Tokens: +// +// STREAM-START(utf-8) +// FLOW-MAPPING-START +// KEY +// SCALAR("a simple key",plain) +// VALUE +// SCALAR("a value",plain) +// FLOW-ENTRY +// KEY +// SCALAR("a complex key",plain) +// VALUE +// SCALAR("another value",plain) +// FLOW-ENTRY +// FLOW-MAPPING-END +// STREAM-END +// +// A simple key is a key which is not denoted by the '?' indicator. Note that +// the Scanner still produce the KEY token whenever it encounters a simple key. +// +// For scanning block collections, the following tokens are used (note that we +// repeat KEY and VALUE here): +// +// BLOCK-SEQUENCE-START +// BLOCK-MAPPING-START +// BLOCK-END +// BLOCK-ENTRY +// KEY +// VALUE +// +// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation +// increase that precedes a block collection (cf. the INDENT token in Python). +// The token BLOCK-END denote indentation decrease that ends a block collection +// (cf. the DEDENT token in Python). However YAML has some syntax pecularities +// that makes detections of these tokens more complex. +// +// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators +// '-', '?', and ':' correspondingly. +// +// The following examples show how the tokens BLOCK-SEQUENCE-START, +// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner: +// +// 1. Block sequences: +// +// - item 1 +// - item 2 +// - +// - item 3.1 +// - item 3.2 +// - +// key 1: value 1 +// key 2: value 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-ENTRY +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 3.1",plain) +// BLOCK-ENTRY +// SCALAR("item 3.2",plain) +// BLOCK-END +// BLOCK-ENTRY +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// 2. Block mappings: +// +// a simple key: a value # The KEY token is produced here. +// ? a complex key +// : another value +// a mapping: +// key 1: value 1 +// key 2: value 2 +// a sequence: +// - item 1 +// - item 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-MAPPING-START +// KEY +// SCALAR("a simple key",plain) +// VALUE +// SCALAR("a value",plain) +// KEY +// SCALAR("a complex key",plain) +// VALUE +// SCALAR("another value",plain) +// KEY +// SCALAR("a mapping",plain) +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// KEY +// SCALAR("a sequence",plain) +// VALUE +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// YAML does not always require to start a new block collection from a new +// line. If the current line contains only '-', '?', and ':' indicators, a new +// block collection may start at the current line. The following examples +// illustrate this case: +// +// 1. Collections in a sequence: +// +// - - item 1 +// - item 2 +// - key 1: value 1 +// key 2: value 2 +// - ? complex key +// : complex value +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// BLOCK-ENTRY +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// BLOCK-ENTRY +// BLOCK-MAPPING-START +// KEY +// SCALAR("complex key") +// VALUE +// SCALAR("complex value") +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// 2. Collections in a mapping: +// +// ? a sequence +// : - item 1 +// - item 2 +// ? a mapping +// : key 1: value 1 +// key 2: value 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-MAPPING-START +// KEY +// SCALAR("a sequence",plain) +// VALUE +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// KEY +// SCALAR("a mapping",plain) +// VALUE +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// YAML also permits non-indented sequences if they are included into a block +// mapping. In this case, the token BLOCK-SEQUENCE-START is not produced: +// +// key: +// - item 1 # BLOCK-SEQUENCE-START is NOT produced here. +// - item 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-MAPPING-START +// KEY +// SCALAR("key",plain) +// VALUE +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// + +// Ensure that the buffer contains the required number of characters. +// Return true on success, false on failure (reader error or memory error). +func cache(parser *yaml_parser_t, length int) bool { + // [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B) + return parser.unread >= length || yaml_parser_update_buffer(parser, length) +} + +// Advance the buffer pointer. +func skip(parser *yaml_parser_t) { + if !is_blank(parser.buffer, parser.buffer_pos) { + parser.newlines = 0 + } + parser.mark.index++ + parser.mark.column++ + parser.unread-- + parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) +} + +func skip_line(parser *yaml_parser_t) { + if is_crlf(parser.buffer, parser.buffer_pos) { + parser.mark.index += 2 + parser.mark.column = 0 + parser.mark.line++ + parser.unread -= 2 + parser.buffer_pos += 2 + parser.newlines++ + } else if is_break(parser.buffer, parser.buffer_pos) { + parser.mark.index++ + parser.mark.column = 0 + parser.mark.line++ + parser.unread-- + parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) + parser.newlines++ + } +} + +// Copy a character to a string buffer and advance pointers. +func read(parser *yaml_parser_t, s []byte) []byte { + if !is_blank(parser.buffer, parser.buffer_pos) { + parser.newlines = 0 + } + w := width(parser.buffer[parser.buffer_pos]) + if w == 0 { + panic("invalid character sequence") + } + if len(s) == 0 { + s = make([]byte, 0, 32) + } + if w == 1 && len(s)+w <= cap(s) { + s = s[:len(s)+1] + s[len(s)-1] = parser.buffer[parser.buffer_pos] + parser.buffer_pos++ + } else { + s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...) + parser.buffer_pos += w + } + parser.mark.index++ + parser.mark.column++ + parser.unread-- + return s +} + +// Copy a line break character to a string buffer and advance pointers. +func read_line(parser *yaml_parser_t, s []byte) []byte { + buf := parser.buffer + pos := parser.buffer_pos + switch { + case buf[pos] == '\r' && buf[pos+1] == '\n': + // CR LF . LF + s = append(s, '\n') + parser.buffer_pos += 2 + parser.mark.index++ + parser.unread-- + case buf[pos] == '\r' || buf[pos] == '\n': + // CR|LF . LF + s = append(s, '\n') + parser.buffer_pos += 1 + case buf[pos] == '\xC2' && buf[pos+1] == '\x85': + // NEL . LF + s = append(s, '\n') + parser.buffer_pos += 2 + case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'): + // LS|PS . LS|PS + s = append(s, buf[parser.buffer_pos:pos+3]...) + parser.buffer_pos += 3 + default: + return s + } + parser.mark.index++ + parser.mark.column = 0 + parser.mark.line++ + parser.unread-- + parser.newlines++ + return s +} + +// Get the next token. +func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool { + // Erase the token object. + *token = yaml_token_t{} // [Go] Is this necessary? + + // No tokens after STREAM-END or error. + if parser.stream_end_produced || parser.error != yaml_NO_ERROR { + return true + } + + // Ensure that the tokens queue contains enough tokens. + if !parser.token_available { + if !yaml_parser_fetch_more_tokens(parser) { + return false + } + } + + // Fetch the next token from the queue. + *token = parser.tokens[parser.tokens_head] + parser.tokens_head++ + parser.tokens_parsed++ + parser.token_available = false + + if token.typ == yaml_STREAM_END_TOKEN { + parser.stream_end_produced = true + } + return true +} + +// Set the scanner error and return false. +func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool { + parser.error = yaml_SCANNER_ERROR + parser.context = context + parser.context_mark = context_mark + parser.problem = problem + parser.problem_mark = parser.mark + return false +} + +func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool { + context := "while parsing a tag" + if directive { + context = "while parsing a %TAG directive" + } + return yaml_parser_set_scanner_error(parser, context, context_mark, problem) +} + +func trace(args ...interface{}) func() { + pargs := append([]interface{}{"+++"}, args...) + fmt.Println(pargs...) + pargs = append([]interface{}{"---"}, args...) + return func() { fmt.Println(pargs...) } +} + +// Ensure that the tokens queue contains at least one token which can be +// returned to the Parser. +func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool { + // While we need more tokens to fetch, do it. + for { + // [Go] The comment parsing logic requires a lookahead of two tokens + // so that foot comments may be parsed in time of associating them + // with the tokens that are parsed before them, and also for line + // comments to be transformed into head comments in some edge cases. + if parser.tokens_head < len(parser.tokens)-2 { + // If a potential simple key is at the head position, we need to fetch + // the next token to disambiguate it. + head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed] + if !ok { + break + } else if valid, ok := yaml_simple_key_is_valid(parser, &parser.simple_keys[head_tok_idx]); !ok { + return false + } else if !valid { + break + } + } + // Fetch the next token. + if !yaml_parser_fetch_next_token(parser) { + return false + } + } + + parser.token_available = true + return true +} + +// The dispatcher for token fetchers. +func yaml_parser_fetch_next_token(parser *yaml_parser_t) (ok bool) { + // Ensure that the buffer is initialized. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + // Check if we just started scanning. Fetch STREAM-START then. + if !parser.stream_start_produced { + return yaml_parser_fetch_stream_start(parser) + } + + scan_mark := parser.mark + + // Eat whitespaces and comments until we reach the next token. + if !yaml_parser_scan_to_next_token(parser) { + return false + } + + // [Go] While unrolling indents, transform the head comments of prior + // indentation levels observed after scan_start into foot comments at + // the respective indexes. + + // Check the indentation level against the current column. + if !yaml_parser_unroll_indent(parser, parser.mark.column, scan_mark) { + return false + } + + // Ensure that the buffer contains at least 4 characters. 4 is the length + // of the longest indicators ('--- ' and '... '). + if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { + return false + } + + // Is it the end of the stream? + if is_z(parser.buffer, parser.buffer_pos) { + return yaml_parser_fetch_stream_end(parser) + } + + // Is it a directive? + if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' { + return yaml_parser_fetch_directive(parser) + } + + buf := parser.buffer + pos := parser.buffer_pos + + // Is it the document start indicator? + if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) { + return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN) + } + + // Is it the document end indicator? + if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) { + return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN) + } + + comment_mark := parser.mark + if len(parser.tokens) > 0 && (parser.flow_level == 0 && buf[pos] == ':' || parser.flow_level > 0 && buf[pos] == ',') { + // Associate any following comments with the prior token. + comment_mark = parser.tokens[len(parser.tokens)-1].start_mark + } + defer func() { + if !ok { + return + } + if len(parser.tokens) > 0 && parser.tokens[len(parser.tokens)-1].typ == yaml_BLOCK_ENTRY_TOKEN { + // Sequence indicators alone have no line comments. It becomes + // a head comment for whatever follows. + return + } + if !yaml_parser_scan_line_comment(parser, comment_mark) { + ok = false + return + } + }() + + // Is it the flow sequence start indicator? + if buf[pos] == '[' { + return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN) + } + + // Is it the flow mapping start indicator? + if parser.buffer[parser.buffer_pos] == '{' { + return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN) + } + + // Is it the flow sequence end indicator? + if parser.buffer[parser.buffer_pos] == ']' { + return yaml_parser_fetch_flow_collection_end(parser, + yaml_FLOW_SEQUENCE_END_TOKEN) + } + + // Is it the flow mapping end indicator? + if parser.buffer[parser.buffer_pos] == '}' { + return yaml_parser_fetch_flow_collection_end(parser, + yaml_FLOW_MAPPING_END_TOKEN) + } + + // Is it the flow entry indicator? + if parser.buffer[parser.buffer_pos] == ',' { + return yaml_parser_fetch_flow_entry(parser) + } + + // Is it the block entry indicator? + if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) { + return yaml_parser_fetch_block_entry(parser) + } + + // Is it the key indicator? + if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { + return yaml_parser_fetch_key(parser) + } + + // Is it the value indicator? + if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { + return yaml_parser_fetch_value(parser) + } + + // Is it an alias? + if parser.buffer[parser.buffer_pos] == '*' { + return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN) + } + + // Is it an anchor? + if parser.buffer[parser.buffer_pos] == '&' { + return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN) + } + + // Is it a tag? + if parser.buffer[parser.buffer_pos] == '!' { + return yaml_parser_fetch_tag(parser) + } + + // Is it a literal scalar? + if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 { + return yaml_parser_fetch_block_scalar(parser, true) + } + + // Is it a folded scalar? + if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 { + return yaml_parser_fetch_block_scalar(parser, false) + } + + // Is it a single-quoted scalar? + if parser.buffer[parser.buffer_pos] == '\'' { + return yaml_parser_fetch_flow_scalar(parser, true) + } + + // Is it a double-quoted scalar? + if parser.buffer[parser.buffer_pos] == '"' { + return yaml_parser_fetch_flow_scalar(parser, false) + } + + // Is it a plain scalar? + // + // A plain scalar may start with any non-blank characters except + // + // '-', '?', ':', ',', '[', ']', '{', '}', + // '#', '&', '*', '!', '|', '>', '\'', '\"', + // '%', '@', '`'. + // + // In the block context (and, for the '-' indicator, in the flow context + // too), it may also start with the characters + // + // '-', '?', ':' + // + // if it is followed by a non-space character. + // + // The last rule is more restrictive than the specification requires. + // [Go] TODO Make this logic more reasonable. + //switch parser.buffer[parser.buffer_pos] { + //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`': + //} + if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' || + parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' || + parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' || + parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || + parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' || + parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' || + parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' || + parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' || + parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' || + parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') || + (parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) || + (parser.flow_level == 0 && + (parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') && + !is_blankz(parser.buffer, parser.buffer_pos+1)) { + return yaml_parser_fetch_plain_scalar(parser) + } + + // If we don't determine the token type so far, it is an error. + return yaml_parser_set_scanner_error(parser, + "while scanning for the next token", parser.mark, + "found character that cannot start any token") +} + +func yaml_simple_key_is_valid(parser *yaml_parser_t, simple_key *yaml_simple_key_t) (valid, ok bool) { + if !simple_key.possible { + return false, true + } + + // The 1.2 specification says: + // + // "If the ? indicator is omitted, parsing needs to see past the + // implicit key to recognize it as such. To limit the amount of + // lookahead required, the “:” indicator must appear at most 1024 + // Unicode characters beyond the start of the key. In addition, the key + // is restricted to a single line." + // + if simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index { + // Check if the potential simple key to be removed is required. + if simple_key.required { + return false, yaml_parser_set_scanner_error(parser, + "while scanning a simple key", simple_key.mark, + "could not find expected ':'") + } + simple_key.possible = false + return false, true + } + return true, true +} + +// Check if a simple key may start at the current position and add it if +// needed. +func yaml_parser_save_simple_key(parser *yaml_parser_t) bool { + // A simple key is required at the current position if the scanner is in + // the block context and the current column coincides with the indentation + // level. + + required := parser.flow_level == 0 && parser.indent == parser.mark.column + + // + // If the current position may start a simple key, save it. + // + if parser.simple_key_allowed { + simple_key := yaml_simple_key_t{ + possible: true, + required: required, + token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), + mark: parser.mark, + } + + if !yaml_parser_remove_simple_key(parser) { + return false + } + parser.simple_keys[len(parser.simple_keys)-1] = simple_key + parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1 + } + return true +} + +// Remove a potential simple key at the current flow level. +func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool { + i := len(parser.simple_keys) - 1 + if parser.simple_keys[i].possible { + // If the key is required, it is an error. + if parser.simple_keys[i].required { + return yaml_parser_set_scanner_error(parser, + "while scanning a simple key", parser.simple_keys[i].mark, + "could not find expected ':'") + } + // Remove the key from the stack. + parser.simple_keys[i].possible = false + delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number) + } + return true +} + +// max_flow_level limits the flow_level +const max_flow_level = 10000 + +// Increase the flow level and resize the simple key list if needed. +func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { + // Reset the simple key on the next level. + parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{ + possible: false, + required: false, + token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), + mark: parser.mark, + }) + + // Increase the flow level. + parser.flow_level++ + if parser.flow_level > max_flow_level { + return yaml_parser_set_scanner_error(parser, + "while increasing flow level", parser.simple_keys[len(parser.simple_keys)-1].mark, + fmt.Sprintf("exceeded max depth of %d", max_flow_level)) + } + return true +} + +// Decrease the flow level. +func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool { + if parser.flow_level > 0 { + parser.flow_level-- + last := len(parser.simple_keys) - 1 + delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number) + parser.simple_keys = parser.simple_keys[:last] + } + return true +} + +// max_indents limits the indents stack size +const max_indents = 10000 + +// Push the current indentation level to the stack and set the new level +// the current column is greater than the indentation level. In this case, +// append or insert the specified token into the token queue. +func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool { + // In the flow context, do nothing. + if parser.flow_level > 0 { + return true + } + + if parser.indent < column { + // Push the current indentation level to the stack and set the new + // indentation level. + parser.indents = append(parser.indents, parser.indent) + parser.indent = column + if len(parser.indents) > max_indents { + return yaml_parser_set_scanner_error(parser, + "while increasing indent level", parser.simple_keys[len(parser.simple_keys)-1].mark, + fmt.Sprintf("exceeded max depth of %d", max_indents)) + } + + // Create a token and insert it into the queue. + token := yaml_token_t{ + typ: typ, + start_mark: mark, + end_mark: mark, + } + if number > -1 { + number -= parser.tokens_parsed + } + yaml_insert_token(parser, number, &token) + } + return true +} + +// Pop indentation levels from the indents stack until the current level +// becomes less or equal to the column. For each indentation level, append +// the BLOCK-END token. +func yaml_parser_unroll_indent(parser *yaml_parser_t, column int, scan_mark yaml_mark_t) bool { + // In the flow context, do nothing. + if parser.flow_level > 0 { + return true + } + + block_mark := scan_mark + block_mark.index-- + + // Loop through the indentation levels in the stack. + for parser.indent > column { + + // [Go] Reposition the end token before potential following + // foot comments of parent blocks. For that, search + // backwards for recent comments that were at the same + // indent as the block that is ending now. + stop_index := block_mark.index + for i := len(parser.comments) - 1; i >= 0; i-- { + comment := &parser.comments[i] + + if comment.end_mark.index < stop_index { + // Don't go back beyond the start of the comment/whitespace scan, unless column < 0. + // If requested indent column is < 0, then the document is over and everything else + // is a foot anyway. + break + } + if comment.start_mark.column == parser.indent+1 { + // This is a good match. But maybe there's a former comment + // at that same indent level, so keep searching. + block_mark = comment.start_mark + } + + // While the end of the former comment matches with + // the start of the following one, we know there's + // nothing in between and scanning is still safe. + stop_index = comment.scan_mark.index + } + + // Create a token and append it to the queue. + token := yaml_token_t{ + typ: yaml_BLOCK_END_TOKEN, + start_mark: block_mark, + end_mark: block_mark, + } + yaml_insert_token(parser, -1, &token) + + // Pop the indentation level. + parser.indent = parser.indents[len(parser.indents)-1] + parser.indents = parser.indents[:len(parser.indents)-1] + } + return true +} + +// Initialize the scanner and produce the STREAM-START token. +func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool { + + // Set the initial indentation. + parser.indent = -1 + + // Initialize the simple key stack. + parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) + + parser.simple_keys_by_tok = make(map[int]int) + + // A simple key is allowed at the beginning of the stream. + parser.simple_key_allowed = true + + // We have started. + parser.stream_start_produced = true + + // Create the STREAM-START token and append it to the queue. + token := yaml_token_t{ + typ: yaml_STREAM_START_TOKEN, + start_mark: parser.mark, + end_mark: parser.mark, + encoding: parser.encoding, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the STREAM-END token and shut down the scanner. +func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool { + + // Force new line. + if parser.mark.column != 0 { + parser.mark.column = 0 + parser.mark.line++ + } + + // Reset the indentation level. + if !yaml_parser_unroll_indent(parser, -1, parser.mark) { + return false + } + + // Reset simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + parser.simple_key_allowed = false + + // Create the STREAM-END token and append it to the queue. + token := yaml_token_t{ + typ: yaml_STREAM_END_TOKEN, + start_mark: parser.mark, + end_mark: parser.mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token. +func yaml_parser_fetch_directive(parser *yaml_parser_t) bool { + // Reset the indentation level. + if !yaml_parser_unroll_indent(parser, -1, parser.mark) { + return false + } + + // Reset simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + parser.simple_key_allowed = false + + // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. + token := yaml_token_t{} + if !yaml_parser_scan_directive(parser, &token) { + return false + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the DOCUMENT-START or DOCUMENT-END token. +func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool { + // Reset the indentation level. + if !yaml_parser_unroll_indent(parser, -1, parser.mark) { + return false + } + + // Reset simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + parser.simple_key_allowed = false + + // Consume the token. + start_mark := parser.mark + + skip(parser) + skip(parser) + skip(parser) + + end_mark := parser.mark + + // Create the DOCUMENT-START or DOCUMENT-END token. + token := yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token. +func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool { + + // The indicators '[' and '{' may start a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // Increase the flow level. + if !yaml_parser_increase_flow_level(parser) { + return false + } + + // A simple key may follow the indicators '[' and '{'. + parser.simple_key_allowed = true + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. + token := yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token. +func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool { + // Reset any potential simple key on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Decrease the flow level. + if !yaml_parser_decrease_flow_level(parser) { + return false + } + + // No simple keys after the indicators ']' and '}'. + parser.simple_key_allowed = false + + // Consume the token. + + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. + token := yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the FLOW-ENTRY token. +func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool { + // Reset any potential simple keys on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Simple keys are allowed after ','. + parser.simple_key_allowed = true + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the FLOW-ENTRY token and append it to the queue. + token := yaml_token_t{ + typ: yaml_FLOW_ENTRY_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the BLOCK-ENTRY token. +func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool { + // Check if the scanner is in the block context. + if parser.flow_level == 0 { + // Check if we are allowed to start a new entry. + if !parser.simple_key_allowed { + return yaml_parser_set_scanner_error(parser, "", parser.mark, + "block sequence entries are not allowed in this context") + } + // Add the BLOCK-SEQUENCE-START token if needed. + if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) { + return false + } + } else { + // It is an error for the '-' indicator to occur in the flow context, + // but we let the Parser detect and report about it because the Parser + // is able to point to the context. + } + + // Reset any potential simple keys on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Simple keys are allowed after '-'. + parser.simple_key_allowed = true + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the BLOCK-ENTRY token and append it to the queue. + token := yaml_token_t{ + typ: yaml_BLOCK_ENTRY_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the KEY token. +func yaml_parser_fetch_key(parser *yaml_parser_t) bool { + + // In the block context, additional checks are required. + if parser.flow_level == 0 { + // Check if we are allowed to start a new key (not nessesary simple). + if !parser.simple_key_allowed { + return yaml_parser_set_scanner_error(parser, "", parser.mark, + "mapping keys are not allowed in this context") + } + // Add the BLOCK-MAPPING-START token if needed. + if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { + return false + } + } + + // Reset any potential simple keys on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Simple keys are allowed after '?' in the block context. + parser.simple_key_allowed = parser.flow_level == 0 + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the KEY token and append it to the queue. + token := yaml_token_t{ + typ: yaml_KEY_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the VALUE token. +func yaml_parser_fetch_value(parser *yaml_parser_t) bool { + + simple_key := &parser.simple_keys[len(parser.simple_keys)-1] + + // Have we found a simple key? + if valid, ok := yaml_simple_key_is_valid(parser, simple_key); !ok { + return false + + } else if valid { + + // Create the KEY token and insert it into the queue. + token := yaml_token_t{ + typ: yaml_KEY_TOKEN, + start_mark: simple_key.mark, + end_mark: simple_key.mark, + } + yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token) + + // In the block context, we may need to add the BLOCK-MAPPING-START token. + if !yaml_parser_roll_indent(parser, simple_key.mark.column, + simple_key.token_number, + yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) { + return false + } + + // Remove the simple key. + simple_key.possible = false + delete(parser.simple_keys_by_tok, simple_key.token_number) + + // A simple key cannot follow another simple key. + parser.simple_key_allowed = false + + } else { + // The ':' indicator follows a complex key. + + // In the block context, extra checks are required. + if parser.flow_level == 0 { + + // Check if we are allowed to start a complex value. + if !parser.simple_key_allowed { + return yaml_parser_set_scanner_error(parser, "", parser.mark, + "mapping values are not allowed in this context") + } + + // Add the BLOCK-MAPPING-START token if needed. + if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { + return false + } + } + + // Simple keys after ':' are allowed in the block context. + parser.simple_key_allowed = parser.flow_level == 0 + } + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the VALUE token and append it to the queue. + token := yaml_token_t{ + typ: yaml_VALUE_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the ALIAS or ANCHOR token. +func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool { + // An anchor or an alias could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow an anchor or an alias. + parser.simple_key_allowed = false + + // Create the ALIAS or ANCHOR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_anchor(parser, &token, typ) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the TAG token. +func yaml_parser_fetch_tag(parser *yaml_parser_t) bool { + // A tag could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow a tag. + parser.simple_key_allowed = false + + // Create the TAG token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_tag(parser, &token) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens. +func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool { + // Remove any potential simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // A simple key may follow a block scalar. + parser.simple_key_allowed = true + + // Create the SCALAR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_block_scalar(parser, &token, literal) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens. +func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool { + // A plain scalar could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow a flow scalar. + parser.simple_key_allowed = false + + // Create the SCALAR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_flow_scalar(parser, &token, single) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the SCALAR(...,plain) token. +func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool { + // A plain scalar could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow a flow scalar. + parser.simple_key_allowed = false + + // Create the SCALAR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_plain_scalar(parser, &token) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Eat whitespaces and comments until the next token is found. +func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool { + + scan_mark := parser.mark + + // Until the next token is not found. + for { + // Allow the BOM mark to start a line. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) { + skip(parser) + } + + // Eat whitespaces. + // Tabs are allowed: + // - in the flow context + // - in the block context, but not at the beginning of the line or + // after '-', '?', or ':' (complex value). + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check if we just had a line comment under a sequence entry that + // looks more like a header to the following content. Similar to this: + // + // - # The comment + // - Some data + // + // If so, transform the line comment to a head comment and reposition. + if len(parser.comments) > 0 && len(parser.tokens) > 1 { + tokenA := parser.tokens[len(parser.tokens)-2] + tokenB := parser.tokens[len(parser.tokens)-1] + comment := &parser.comments[len(parser.comments)-1] + if tokenA.typ == yaml_BLOCK_SEQUENCE_START_TOKEN && tokenB.typ == yaml_BLOCK_ENTRY_TOKEN && len(comment.line) > 0 && !is_break(parser.buffer, parser.buffer_pos) { + // If it was in the prior line, reposition so it becomes a + // header of the follow up token. Otherwise, keep it in place + // so it becomes a header of the former. + comment.head = comment.line + comment.line = nil + if comment.start_mark.line == parser.mark.line-1 { + comment.token_mark = parser.mark + } + } + } + + // Eat a comment until a line break. + if parser.buffer[parser.buffer_pos] == '#' { + if !yaml_parser_scan_comments(parser, scan_mark) { + return false + } + } + + // If it is a line break, eat it. + if is_break(parser.buffer, parser.buffer_pos) { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + skip_line(parser) + + // In the block context, a new line may start a simple key. + if parser.flow_level == 0 { + parser.simple_key_allowed = true + } + } else { + break // We have found a token. + } + } + + return true +} + +// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token. +// +// Scope: +// %YAML 1.1 # a comment \n +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// %TAG !yaml! tag:yaml.org,2002: \n +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// +func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool { + // Eat '%'. + start_mark := parser.mark + skip(parser) + + // Scan the directive name. + var name []byte + if !yaml_parser_scan_directive_name(parser, start_mark, &name) { + return false + } + + // Is it a YAML directive? + if bytes.Equal(name, []byte("YAML")) { + // Scan the VERSION directive value. + var major, minor int8 + if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) { + return false + } + end_mark := parser.mark + + // Create a VERSION-DIRECTIVE token. + *token = yaml_token_t{ + typ: yaml_VERSION_DIRECTIVE_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + major: major, + minor: minor, + } + + // Is it a TAG directive? + } else if bytes.Equal(name, []byte("TAG")) { + // Scan the TAG directive value. + var handle, prefix []byte + if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) { + return false + } + end_mark := parser.mark + + // Create a TAG-DIRECTIVE token. + *token = yaml_token_t{ + typ: yaml_TAG_DIRECTIVE_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: handle, + prefix: prefix, + } + + // Unknown directive. + } else { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "found unknown directive name") + return false + } + + // Eat the rest of the line including any comments. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + if parser.buffer[parser.buffer_pos] == '#' { + // [Go] Discard this inline comment for the time being. + //if !yaml_parser_scan_line_comment(parser, start_mark) { + // return false + //} + for !is_breakz(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + } + + // Check if we are at the end of the line. + if !is_breakz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "did not find expected comment or line break") + return false + } + + // Eat a line break. + if is_break(parser.buffer, parser.buffer_pos) { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + skip_line(parser) + } + + return true +} + +// Scan the directive name. +// +// Scope: +// %YAML 1.1 # a comment \n +// ^^^^ +// %TAG !yaml! tag:yaml.org,2002: \n +// ^^^ +// +func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool { + // Consume the directive name. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + var s []byte + for is_alpha(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check if the name is empty. + if len(s) == 0 { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "could not find expected directive name") + return false + } + + // Check for an blank character after the name. + if !is_blankz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "found unexpected non-alphabetical character") + return false + } + *name = s + return true +} + +// Scan the value of VERSION-DIRECTIVE. +// +// Scope: +// %YAML 1.1 # a comment \n +// ^^^^^^ +func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool { + // Eat whitespaces. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Consume the major version number. + if !yaml_parser_scan_version_directive_number(parser, start_mark, major) { + return false + } + + // Eat '.'. + if parser.buffer[parser.buffer_pos] != '.' { + return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", + start_mark, "did not find expected digit or '.' character") + } + + skip(parser) + + // Consume the minor version number. + if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) { + return false + } + return true +} + +const max_number_length = 2 + +// Scan the version number of VERSION-DIRECTIVE. +// +// Scope: +// %YAML 1.1 # a comment \n +// ^ +// %YAML 1.1 # a comment \n +// ^ +func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool { + + // Repeat while the next character is digit. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + var value, length int8 + for is_digit(parser.buffer, parser.buffer_pos) { + // Check if the number is too long. + length++ + if length > max_number_length { + return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", + start_mark, "found extremely long version number") + } + value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos)) + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check if the number was present. + if length == 0 { + return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", + start_mark, "did not find expected version number") + } + *number = value + return true +} + +// Scan the value of a TAG-DIRECTIVE token. +// +// Scope: +// %TAG !yaml! tag:yaml.org,2002: \n +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// +func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool { + var handle_value, prefix_value []byte + + // Eat whitespaces. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Scan a handle. + if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) { + return false + } + + // Expect a whitespace. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if !is_blank(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", + start_mark, "did not find expected whitespace") + return false + } + + // Eat whitespaces. + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Scan a prefix. + if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) { + return false + } + + // Expect a whitespace or line break. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if !is_blankz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", + start_mark, "did not find expected whitespace or line break") + return false + } + + *handle = handle_value + *prefix = prefix_value + return true +} + +func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool { + var s []byte + + // Eat the indicator character. + start_mark := parser.mark + skip(parser) + + // Consume the value. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_alpha(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + end_mark := parser.mark + + /* + * Check if length of the anchor is greater than 0 and it is followed by + * a whitespace character or one of the indicators: + * + * '?', ':', ',', ']', '}', '%', '@', '`'. + */ + + if len(s) == 0 || + !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' || + parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' || + parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' || + parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' || + parser.buffer[parser.buffer_pos] == '`') { + context := "while scanning an alias" + if typ == yaml_ANCHOR_TOKEN { + context = "while scanning an anchor" + } + yaml_parser_set_scanner_error(parser, context, start_mark, + "did not find expected alphabetic or numeric character") + return false + } + + // Create a token. + *token = yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + value: s, + } + + return true +} + +/* + * Scan a TAG token. + */ + +func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool { + var handle, suffix []byte + + start_mark := parser.mark + + // Check if the tag is in the canonical form. + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + if parser.buffer[parser.buffer_pos+1] == '<' { + // Keep the handle as '' + + // Eat '!<' + skip(parser) + skip(parser) + + // Consume the tag value. + if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { + return false + } + + // Check for '>' and eat it. + if parser.buffer[parser.buffer_pos] != '>' { + yaml_parser_set_scanner_error(parser, "while scanning a tag", + start_mark, "did not find the expected '>'") + return false + } + + skip(parser) + } else { + // The tag has either the '!suffix' or the '!handle!suffix' form. + + // First, try to scan a handle. + if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) { + return false + } + + // Check if it is, indeed, handle. + if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' { + // Scan the suffix now. + if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { + return false + } + } else { + // It wasn't a handle after all. Scan the rest of the tag. + if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) { + return false + } + + // Set the handle to '!'. + handle = []byte{'!'} + + // A special case: the '!' tag. Set the handle to '' and the + // suffix to '!'. + if len(suffix) == 0 { + handle, suffix = suffix, handle + } + } + } + + // Check the character which ends the tag. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if !is_blankz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a tag", + start_mark, "did not find expected whitespace or line break") + return false + } + + end_mark := parser.mark + + // Create a token. + *token = yaml_token_t{ + typ: yaml_TAG_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: handle, + suffix: suffix, + } + return true +} + +// Scan a tag handle. +func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool { + // Check the initial '!' character. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if parser.buffer[parser.buffer_pos] != '!' { + yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find expected '!'") + return false + } + + var s []byte + + // Copy the '!' character. + s = read(parser, s) + + // Copy all subsequent alphabetical and numerical characters. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for is_alpha(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check if the trailing character is '!' and copy it. + if parser.buffer[parser.buffer_pos] == '!' { + s = read(parser, s) + } else { + // It's either the '!' tag or not really a tag handle. If it's a %TAG + // directive, it's an error. If it's a tag token, it must be a part of URI. + if directive && string(s) != "!" { + yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find expected '!'") + return false + } + } + + *handle = s + return true +} + +// Scan a tag. +func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool { + //size_t length = head ? strlen((char *)head) : 0 + var s []byte + hasTag := len(head) > 0 + + // Copy the head if needed. + // + // Note that we don't copy the leading '!' character. + if len(head) > 1 { + s = append(s, head[1:]...) + } + + // Scan the tag. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + // The set of characters that may appear in URI is as follows: + // + // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&', + // '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']', + // '%'. + // [Go] TODO Convert this into more reasonable logic. + for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' || + parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' || + parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' || + parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' || + parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' || + parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' || + parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' || + parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' || + parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' || + parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' || + parser.buffer[parser.buffer_pos] == '%' { + // Check if it is a URI-escape sequence. + if parser.buffer[parser.buffer_pos] == '%' { + if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) { + return false + } + } else { + s = read(parser, s) + } + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + hasTag = true + } + + if !hasTag { + yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find expected tag URI") + return false + } + *uri = s + return true +} + +// Decode an URI-escape sequence corresponding to a single UTF-8 character. +func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool { + + // Decode the required number of characters. + w := 1024 + for w > 0 { + // Check for a URI-escaped octet. + if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { + return false + } + + if !(parser.buffer[parser.buffer_pos] == '%' && + is_hex(parser.buffer, parser.buffer_pos+1) && + is_hex(parser.buffer, parser.buffer_pos+2)) { + return yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find URI escaped octet") + } + + // Get the octet. + octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2)) + + // If it is the leading octet, determine the length of the UTF-8 sequence. + if w == 1024 { + w = width(octet) + if w == 0 { + return yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "found an incorrect leading UTF-8 octet") + } + } else { + // Check if the trailing octet is correct. + if octet&0xC0 != 0x80 { + return yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "found an incorrect trailing UTF-8 octet") + } + } + + // Copy the octet and move the pointers. + *s = append(*s, octet) + skip(parser) + skip(parser) + skip(parser) + w-- + } + return true +} + +// Scan a block scalar. +func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool { + // Eat the indicator '|' or '>'. + start_mark := parser.mark + skip(parser) + + // Scan the additional block scalar indicators. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + // Check for a chomping indicator. + var chomping, increment int + if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { + // Set the chomping method and eat the indicator. + if parser.buffer[parser.buffer_pos] == '+' { + chomping = +1 + } else { + chomping = -1 + } + skip(parser) + + // Check for an indentation indicator. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if is_digit(parser.buffer, parser.buffer_pos) { + // Check that the indentation is greater than 0. + if parser.buffer[parser.buffer_pos] == '0' { + yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "found an indentation indicator equal to 0") + return false + } + + // Get the indentation level and eat the indicator. + increment = as_digit(parser.buffer, parser.buffer_pos) + skip(parser) + } + + } else if is_digit(parser.buffer, parser.buffer_pos) { + // Do the same as above, but in the opposite order. + + if parser.buffer[parser.buffer_pos] == '0' { + yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "found an indentation indicator equal to 0") + return false + } + increment = as_digit(parser.buffer, parser.buffer_pos) + skip(parser) + + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { + if parser.buffer[parser.buffer_pos] == '+' { + chomping = +1 + } else { + chomping = -1 + } + skip(parser) + } + } + + // Eat whitespaces and comments to the end of the line. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + if parser.buffer[parser.buffer_pos] == '#' { + if !yaml_parser_scan_line_comment(parser, start_mark) { + return false + } + for !is_breakz(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + } + + // Check if we are at the end of the line. + if !is_breakz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "did not find expected comment or line break") + return false + } + + // Eat a line break. + if is_break(parser.buffer, parser.buffer_pos) { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + skip_line(parser) + } + + end_mark := parser.mark + + // Set the indentation level if it was specified. + var indent int + if increment > 0 { + if parser.indent >= 0 { + indent = parser.indent + increment + } else { + indent = increment + } + } + + // Scan the leading line breaks and determine the indentation level if needed. + var s, leading_break, trailing_breaks []byte + if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { + return false + } + + // Scan the block scalar content. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + var leading_blank, trailing_blank bool + for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) { + // We are at the beginning of a non-empty line. + + // Is it a trailing whitespace? + trailing_blank = is_blank(parser.buffer, parser.buffer_pos) + + // Check if we need to fold the leading line break. + if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' { + // Do we need to join the lines by space? + if len(trailing_breaks) == 0 { + s = append(s, ' ') + } + } else { + s = append(s, leading_break...) + } + leading_break = leading_break[:0] + + // Append the remaining line breaks. + s = append(s, trailing_breaks...) + trailing_breaks = trailing_breaks[:0] + + // Is it a leading whitespace? + leading_blank = is_blank(parser.buffer, parser.buffer_pos) + + // Consume the current line. + for !is_breakz(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Consume the line break. + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + leading_break = read_line(parser, leading_break) + + // Eat the following indentation spaces and line breaks. + if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { + return false + } + } + + // Chomp the tail. + if chomping != -1 { + s = append(s, leading_break...) + } + if chomping == 1 { + s = append(s, trailing_breaks...) + } + + // Create a token. + *token = yaml_token_t{ + typ: yaml_SCALAR_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: s, + style: yaml_LITERAL_SCALAR_STYLE, + } + if !literal { + token.style = yaml_FOLDED_SCALAR_STYLE + } + return true +} + +// Scan indentation spaces and line breaks for a block scalar. Determine the +// indentation level if needed. +func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool { + *end_mark = parser.mark + + // Eat the indentation spaces and line breaks. + max_indent := 0 + for { + // Eat the indentation spaces. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + if parser.mark.column > max_indent { + max_indent = parser.mark.column + } + + // Check for a tab character messing the indentation. + if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) { + return yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "found a tab character where an indentation space is expected") + } + + // Have we found a non-empty line? + if !is_break(parser.buffer, parser.buffer_pos) { + break + } + + // Consume the line break. + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + // [Go] Should really be returning breaks instead. + *breaks = read_line(parser, *breaks) + *end_mark = parser.mark + } + + // Determine the indentation level if needed. + if *indent == 0 { + *indent = max_indent + if *indent < parser.indent+1 { + *indent = parser.indent + 1 + } + if *indent < 1 { + *indent = 1 + } + } + return true +} + +// Scan a quoted scalar. +func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool { + // Eat the left quote. + start_mark := parser.mark + skip(parser) + + // Consume the content of the quoted scalar. + var s, leading_break, trailing_breaks, whitespaces []byte + for { + // Check that there are no document indicators at the beginning of the line. + if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { + return false + } + + if parser.mark.column == 0 && + ((parser.buffer[parser.buffer_pos+0] == '-' && + parser.buffer[parser.buffer_pos+1] == '-' && + parser.buffer[parser.buffer_pos+2] == '-') || + (parser.buffer[parser.buffer_pos+0] == '.' && + parser.buffer[parser.buffer_pos+1] == '.' && + parser.buffer[parser.buffer_pos+2] == '.')) && + is_blankz(parser.buffer, parser.buffer_pos+3) { + yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", + start_mark, "found unexpected document indicator") + return false + } + + // Check for EOF. + if is_z(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", + start_mark, "found unexpected end of stream") + return false + } + + // Consume non-blank characters. + leading_blanks := false + for !is_blankz(parser.buffer, parser.buffer_pos) { + if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' { + // Is is an escaped single quote. + s = append(s, '\'') + skip(parser) + skip(parser) + + } else if single && parser.buffer[parser.buffer_pos] == '\'' { + // It is a right single quote. + break + } else if !single && parser.buffer[parser.buffer_pos] == '"' { + // It is a right double quote. + break + + } else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) { + // It is an escaped line break. + if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { + return false + } + skip(parser) + skip_line(parser) + leading_blanks = true + break + + } else if !single && parser.buffer[parser.buffer_pos] == '\\' { + // It is an escape sequence. + code_length := 0 + + // Check the escape character. + switch parser.buffer[parser.buffer_pos+1] { + case '0': + s = append(s, 0) + case 'a': + s = append(s, '\x07') + case 'b': + s = append(s, '\x08') + case 't', '\t': + s = append(s, '\x09') + case 'n': + s = append(s, '\x0A') + case 'v': + s = append(s, '\x0B') + case 'f': + s = append(s, '\x0C') + case 'r': + s = append(s, '\x0D') + case 'e': + s = append(s, '\x1B') + case ' ': + s = append(s, '\x20') + case '"': + s = append(s, '"') + case '\'': + s = append(s, '\'') + case '\\': + s = append(s, '\\') + case 'N': // NEL (#x85) + s = append(s, '\xC2') + s = append(s, '\x85') + case '_': // #xA0 + s = append(s, '\xC2') + s = append(s, '\xA0') + case 'L': // LS (#x2028) + s = append(s, '\xE2') + s = append(s, '\x80') + s = append(s, '\xA8') + case 'P': // PS (#x2029) + s = append(s, '\xE2') + s = append(s, '\x80') + s = append(s, '\xA9') + case 'x': + code_length = 2 + case 'u': + code_length = 4 + case 'U': + code_length = 8 + default: + yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", + start_mark, "found unknown escape character") + return false + } + + skip(parser) + skip(parser) + + // Consume an arbitrary escape code. + if code_length > 0 { + var value int + + // Scan the character value. + if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) { + return false + } + for k := 0; k < code_length; k++ { + if !is_hex(parser.buffer, parser.buffer_pos+k) { + yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", + start_mark, "did not find expected hexdecimal number") + return false + } + value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k) + } + + // Check the value and write the character. + if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF { + yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", + start_mark, "found invalid Unicode character escape code") + return false + } + if value <= 0x7F { + s = append(s, byte(value)) + } else if value <= 0x7FF { + s = append(s, byte(0xC0+(value>>6))) + s = append(s, byte(0x80+(value&0x3F))) + } else if value <= 0xFFFF { + s = append(s, byte(0xE0+(value>>12))) + s = append(s, byte(0x80+((value>>6)&0x3F))) + s = append(s, byte(0x80+(value&0x3F))) + } else { + s = append(s, byte(0xF0+(value>>18))) + s = append(s, byte(0x80+((value>>12)&0x3F))) + s = append(s, byte(0x80+((value>>6)&0x3F))) + s = append(s, byte(0x80+(value&0x3F))) + } + + // Advance the pointer. + for k := 0; k < code_length; k++ { + skip(parser) + } + } + } else { + // It is a non-escaped non-blank character. + s = read(parser, s) + } + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + } + + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + // Check if we are at the end of the scalar. + if single { + if parser.buffer[parser.buffer_pos] == '\'' { + break + } + } else { + if parser.buffer[parser.buffer_pos] == '"' { + break + } + } + + // Consume blank characters. + for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { + if is_blank(parser.buffer, parser.buffer_pos) { + // Consume a space or a tab character. + if !leading_blanks { + whitespaces = read(parser, whitespaces) + } else { + skip(parser) + } + } else { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + // Check if it is a first line break. + if !leading_blanks { + whitespaces = whitespaces[:0] + leading_break = read_line(parser, leading_break) + leading_blanks = true + } else { + trailing_breaks = read_line(parser, trailing_breaks) + } + } + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Join the whitespaces or fold line breaks. + if leading_blanks { + // Do we need to fold line breaks? + if len(leading_break) > 0 && leading_break[0] == '\n' { + if len(trailing_breaks) == 0 { + s = append(s, ' ') + } else { + s = append(s, trailing_breaks...) + } + } else { + s = append(s, leading_break...) + s = append(s, trailing_breaks...) + } + trailing_breaks = trailing_breaks[:0] + leading_break = leading_break[:0] + } else { + s = append(s, whitespaces...) + whitespaces = whitespaces[:0] + } + } + + // Eat the right quote. + skip(parser) + end_mark := parser.mark + + // Create a token. + *token = yaml_token_t{ + typ: yaml_SCALAR_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: s, + style: yaml_SINGLE_QUOTED_SCALAR_STYLE, + } + if !single { + token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + return true +} + +// Scan a plain scalar. +func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool { + + var s, leading_break, trailing_breaks, whitespaces []byte + var leading_blanks bool + var indent = parser.indent + 1 + + start_mark := parser.mark + end_mark := parser.mark + + // Consume the content of the plain scalar. + for { + // Check for a document indicator. + if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { + return false + } + if parser.mark.column == 0 && + ((parser.buffer[parser.buffer_pos+0] == '-' && + parser.buffer[parser.buffer_pos+1] == '-' && + parser.buffer[parser.buffer_pos+2] == '-') || + (parser.buffer[parser.buffer_pos+0] == '.' && + parser.buffer[parser.buffer_pos+1] == '.' && + parser.buffer[parser.buffer_pos+2] == '.')) && + is_blankz(parser.buffer, parser.buffer_pos+3) { + break + } + + // Check for a comment. + if parser.buffer[parser.buffer_pos] == '#' { + break + } + + // Consume non-blank characters. + for !is_blankz(parser.buffer, parser.buffer_pos) { + + // Check for indicators that may end a plain scalar. + if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) || + (parser.flow_level > 0 && + (parser.buffer[parser.buffer_pos] == ',' || + parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' || + parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || + parser.buffer[parser.buffer_pos] == '}')) { + break + } + + // Check if we need to join whitespaces and breaks. + if leading_blanks || len(whitespaces) > 0 { + if leading_blanks { + // Do we need to fold line breaks? + if leading_break[0] == '\n' { + if len(trailing_breaks) == 0 { + s = append(s, ' ') + } else { + s = append(s, trailing_breaks...) + } + } else { + s = append(s, leading_break...) + s = append(s, trailing_breaks...) + } + trailing_breaks = trailing_breaks[:0] + leading_break = leading_break[:0] + leading_blanks = false + } else { + s = append(s, whitespaces...) + whitespaces = whitespaces[:0] + } + } + + // Copy the character. + s = read(parser, s) + + end_mark = parser.mark + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + } + + // Is it the end? + if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) { + break + } + + // Consume blank characters. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { + if is_blank(parser.buffer, parser.buffer_pos) { + + // Check for tab characters that abuse indentation. + if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", + start_mark, "found a tab character that violates indentation") + return false + } + + // Consume a space or a tab character. + if !leading_blanks { + whitespaces = read(parser, whitespaces) + } else { + skip(parser) + } + } else { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + // Check if it is a first line break. + if !leading_blanks { + whitespaces = whitespaces[:0] + leading_break = read_line(parser, leading_break) + leading_blanks = true + } else { + trailing_breaks = read_line(parser, trailing_breaks) + } + } + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check indentation level. + if parser.flow_level == 0 && parser.mark.column < indent { + break + } + } + + // Create a token. + *token = yaml_token_t{ + typ: yaml_SCALAR_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: s, + style: yaml_PLAIN_SCALAR_STYLE, + } + + // Note that we change the 'simple_key_allowed' flag. + if leading_blanks { + parser.simple_key_allowed = true + } + return true +} + +func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t) bool { + if parser.newlines > 0 { + return true + } + + var start_mark yaml_mark_t + var text []byte + + for peek := 0; peek < 512; peek++ { + if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) { + break + } + if is_blank(parser.buffer, parser.buffer_pos+peek) { + continue + } + if parser.buffer[parser.buffer_pos+peek] == '#' { + seen := parser.mark.index+peek + for { + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if is_breakz(parser.buffer, parser.buffer_pos) { + if parser.mark.index >= seen { + break + } + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + skip_line(parser) + } else if parser.mark.index >= seen { + if len(text) == 0 { + start_mark = parser.mark + } + text = read(parser, text) + } else { + skip(parser) + } + } + } + break + } + if len(text) > 0 { + parser.comments = append(parser.comments, yaml_comment_t{ + token_mark: token_mark, + start_mark: start_mark, + line: text, + }) + } + return true +} + +func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) bool { + token := parser.tokens[len(parser.tokens)-1] + + if token.typ == yaml_FLOW_ENTRY_TOKEN && len(parser.tokens) > 1 { + token = parser.tokens[len(parser.tokens)-2] + } + + var token_mark = token.start_mark + var start_mark yaml_mark_t + var next_indent = parser.indent + if next_indent < 0 { + next_indent = 0 + } + + var recent_empty = false + var first_empty = parser.newlines <= 1 + + var line = parser.mark.line + var column = parser.mark.column + + var text []byte + + // The foot line is the place where a comment must start to + // still be considered as a foot of the prior content. + // If there's some content in the currently parsed line, then + // the foot is the line below it. + var foot_line = -1 + if scan_mark.line > 0 { + foot_line = parser.mark.line-parser.newlines+1 + if parser.newlines == 0 && parser.mark.column > 1 { + foot_line++ + } + } + + var peek = 0 + for ; peek < 512; peek++ { + if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) { + break + } + column++ + if is_blank(parser.buffer, parser.buffer_pos+peek) { + continue + } + c := parser.buffer[parser.buffer_pos+peek] + var close_flow = parser.flow_level > 0 && (c == ']' || c == '}') + if close_flow || is_breakz(parser.buffer, parser.buffer_pos+peek) { + // Got line break or terminator. + if close_flow || !recent_empty { + if close_flow || first_empty && (start_mark.line == foot_line && token.typ != yaml_VALUE_TOKEN || start_mark.column-1 < next_indent) { + // This is the first empty line and there were no empty lines before, + // so this initial part of the comment is a foot of the prior token + // instead of being a head for the following one. Split it up. + // Alternatively, this might also be the last comment inside a flow + // scope, so it must be a footer. + if len(text) > 0 { + if start_mark.column-1 < next_indent { + // If dedented it's unrelated to the prior token. + token_mark = start_mark + } + parser.comments = append(parser.comments, yaml_comment_t{ + scan_mark: scan_mark, + token_mark: token_mark, + start_mark: start_mark, + end_mark: yaml_mark_t{parser.mark.index + peek, line, column}, + foot: text, + }) + scan_mark = yaml_mark_t{parser.mark.index + peek, line, column} + token_mark = scan_mark + text = nil + } + } else { + if len(text) > 0 && parser.buffer[parser.buffer_pos+peek] != 0 { + text = append(text, '\n') + } + } + } + if !is_break(parser.buffer, parser.buffer_pos+peek) { + break + } + first_empty = false + recent_empty = true + column = 0 + line++ + continue + } + + if len(text) > 0 && (close_flow || column-1 < next_indent && column != start_mark.column) { + // The comment at the different indentation is a foot of the + // preceding data rather than a head of the upcoming one. + parser.comments = append(parser.comments, yaml_comment_t{ + scan_mark: scan_mark, + token_mark: token_mark, + start_mark: start_mark, + end_mark: yaml_mark_t{parser.mark.index + peek, line, column}, + foot: text, + }) + scan_mark = yaml_mark_t{parser.mark.index + peek, line, column} + token_mark = scan_mark + text = nil + } + + if parser.buffer[parser.buffer_pos+peek] != '#' { + break + } + + if len(text) == 0 { + start_mark = yaml_mark_t{parser.mark.index + peek, line, column} + } else { + text = append(text, '\n') + } + + recent_empty = false + + // Consume until after the consumed comment line. + seen := parser.mark.index+peek + for { + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if is_breakz(parser.buffer, parser.buffer_pos) { + if parser.mark.index >= seen { + break + } + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + skip_line(parser) + } else if parser.mark.index >= seen { + text = read(parser, text) + } else { + skip(parser) + } + } + + peek = 0 + column = 0 + line = parser.mark.line + next_indent = parser.indent + if next_indent < 0 { + next_indent = 0 + } + } + + if len(text) > 0 { + parser.comments = append(parser.comments, yaml_comment_t{ + scan_mark: scan_mark, + token_mark: start_mark, + start_mark: start_mark, + end_mark: yaml_mark_t{parser.mark.index + peek - 1, line, column}, + head: text, + }) + } + return true +} diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/sorter.go b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/sorter.go new file mode 100644 index 000000000..9210ece7e --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/sorter.go @@ -0,0 +1,134 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package yaml + +import ( + "reflect" + "unicode" +) + +type keyList []reflect.Value + +func (l keyList) Len() int { return len(l) } +func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } +func (l keyList) Less(i, j int) bool { + a := l[i] + b := l[j] + ak := a.Kind() + bk := b.Kind() + for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { + a = a.Elem() + ak = a.Kind() + } + for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { + b = b.Elem() + bk = b.Kind() + } + af, aok := keyFloat(a) + bf, bok := keyFloat(b) + if aok && bok { + if af != bf { + return af < bf + } + if ak != bk { + return ak < bk + } + return numLess(a, b) + } + if ak != reflect.String || bk != reflect.String { + return ak < bk + } + ar, br := []rune(a.String()), []rune(b.String()) + digits := false + for i := 0; i < len(ar) && i < len(br); i++ { + if ar[i] == br[i] { + digits = unicode.IsDigit(ar[i]) + continue + } + al := unicode.IsLetter(ar[i]) + bl := unicode.IsLetter(br[i]) + if al && bl { + return ar[i] < br[i] + } + if al || bl { + if digits { + return al + } else { + return bl + } + } + var ai, bi int + var an, bn int64 + if ar[i] == '0' || br[i] == '0' { + for j := i - 1; j >= 0 && unicode.IsDigit(ar[j]); j-- { + if ar[j] != '0' { + an = 1 + bn = 1 + break + } + } + } + for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { + an = an*10 + int64(ar[ai]-'0') + } + for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { + bn = bn*10 + int64(br[bi]-'0') + } + if an != bn { + return an < bn + } + if ai != bi { + return ai < bi + } + return ar[i] < br[i] + } + return len(ar) < len(br) +} + +// keyFloat returns a float value for v if it is a number/bool +// and whether it is a number/bool or not. +func keyFloat(v reflect.Value) (f float64, ok bool) { + switch v.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return float64(v.Int()), true + case reflect.Float32, reflect.Float64: + return v.Float(), true + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return float64(v.Uint()), true + case reflect.Bool: + if v.Bool() { + return 1, true + } + return 0, true + } + return 0, false +} + +// numLess returns whether a < b. +// a and b must necessarily have the same kind. +func numLess(a, b reflect.Value) bool { + switch a.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return a.Int() < b.Int() + case reflect.Float32, reflect.Float64: + return a.Float() < b.Float() + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return a.Uint() < b.Uint() + case reflect.Bool: + return !a.Bool() && b.Bool() + } + panic("not a number") +} diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/writerc.go b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/writerc.go new file mode 100644 index 000000000..b8a116bf9 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/writerc.go @@ -0,0 +1,48 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// Copyright (c) 2006-2010 Kirill Simonov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package yaml + +// Set the writer error and return false. +func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { + emitter.error = yaml_WRITER_ERROR + emitter.problem = problem + return false +} + +// Flush the output buffer. +func yaml_emitter_flush(emitter *yaml_emitter_t) bool { + if emitter.write_handler == nil { + panic("write handler not set") + } + + // Check if the buffer is empty. + if emitter.buffer_pos == 0 { + return true + } + + if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { + return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) + } + emitter.buffer_pos = 0 + return true +} diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/yaml.go b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/yaml.go new file mode 100644 index 000000000..bb6418dba --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/yaml.go @@ -0,0 +1,708 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package yaml implements YAML support for the Go language. +// +// Source code and other details for the project are available at GitHub: +// +// https://github.com/go-yaml/yaml +// +package yaml + +import ( + "errors" + "fmt" + "io" + "reflect" + "strings" + "sync" + "unicode/utf8" +) + +// The Unmarshaler interface may be implemented by types to customize their +// behavior when being unmarshaled from a YAML document. +type Unmarshaler interface { + UnmarshalYAML(value *Node) error +} + +type obsoleteUnmarshaler interface { + UnmarshalYAML(unmarshal func(interface{}) error) error +} + +// The Marshaler interface may be implemented by types to customize their +// behavior when being marshaled into a YAML document. The returned value +// is marshaled in place of the original value implementing Marshaler. +// +// If an error is returned by MarshalYAML, the marshaling procedure stops +// and returns with the provided error. +type Marshaler interface { + MarshalYAML() (interface{}, error) +} + +// Unmarshal decodes the first document found within the in byte slice +// and assigns decoded values into the out value. +// +// Maps and pointers (to a struct, string, int, etc) are accepted as out +// values. If an internal pointer within a struct is not initialized, +// the yaml package will initialize it if necessary for unmarshalling +// the provided data. The out parameter must not be nil. +// +// The type of the decoded values should be compatible with the respective +// values in out. If one or more values cannot be decoded due to a type +// mismatches, decoding continues partially until the end of the YAML +// content, and a *yaml.TypeError is returned with details for all +// missed values. +// +// Struct fields are only unmarshalled if they are exported (have an +// upper case first letter), and are unmarshalled using the field name +// lowercased as the default key. Custom keys may be defined via the +// "yaml" name in the field tag: the content preceding the first comma +// is used as the key, and the following comma-separated options are +// used to tweak the marshalling process (see Marshal). +// Conflicting names result in a runtime error. +// +// For example: +// +// type T struct { +// F int `yaml:"a,omitempty"` +// B int +// } +// var t T +// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t) +// +// See the documentation of Marshal for the format of tags and a list of +// supported tag options. +// +func Unmarshal(in []byte, out interface{}) (err error) { + return unmarshal(in, out, false) +} + +// A Decoder reads and decodes YAML values from an input stream. +type Decoder struct { + parser *parser + knownFields bool +} + +// NewDecoder returns a new decoder that reads from r. +// +// The decoder introduces its own buffering and may read +// data from r beyond the YAML values requested. +func NewDecoder(r io.Reader) *Decoder { + return &Decoder{ + parser: newParserFromReader(r), + } +} + +// KnownFields ensures that the keys in decoded mappings to +// exist as fields in the struct being decoded into. +func (dec *Decoder) KnownFields(enable bool) { + dec.knownFields = enable +} + +// Decode reads the next YAML-encoded value from its input +// and stores it in the value pointed to by v. +// +// See the documentation for Unmarshal for details about the +// conversion of YAML into a Go value. +func (dec *Decoder) Decode(v interface{}) (err error) { + d := newDecoder() + d.knownFields = dec.knownFields + defer handleErr(&err) + node := dec.parser.parse() + if node == nil { + return io.EOF + } + out := reflect.ValueOf(v) + if out.Kind() == reflect.Ptr && !out.IsNil() { + out = out.Elem() + } + d.unmarshal(node, out) + if len(d.terrors) > 0 { + return &TypeError{d.terrors} + } + return nil +} + +// Decode decodes the node and stores its data into the value pointed to by v. +// +// See the documentation for Unmarshal for details about the +// conversion of YAML into a Go value. +func (n *Node) Decode(v interface{}) (err error) { + d := newDecoder() + defer handleErr(&err) + out := reflect.ValueOf(v) + if out.Kind() == reflect.Ptr && !out.IsNil() { + out = out.Elem() + } + d.unmarshal(n, out) + if len(d.terrors) > 0 { + return &TypeError{d.terrors} + } + return nil +} + +func unmarshal(in []byte, out interface{}, strict bool) (err error) { + defer handleErr(&err) + d := newDecoder() + p := newParser(in) + defer p.destroy() + node := p.parse() + if node != nil { + v := reflect.ValueOf(out) + if v.Kind() == reflect.Ptr && !v.IsNil() { + v = v.Elem() + } + d.unmarshal(node, v) + } + if len(d.terrors) > 0 { + return &TypeError{d.terrors} + } + return nil +} + +// Marshal serializes the value provided into a YAML document. The structure +// of the generated document will reflect the structure of the value itself. +// Maps and pointers (to struct, string, int, etc) are accepted as the in value. +// +// Struct fields are only marshalled if they are exported (have an upper case +// first letter), and are marshalled using the field name lowercased as the +// default key. Custom keys may be defined via the "yaml" name in the field +// tag: the content preceding the first comma is used as the key, and the +// following comma-separated options are used to tweak the marshalling process. +// Conflicting names result in a runtime error. +// +// The field tag format accepted is: +// +// `(...) yaml:"[][,[,]]" (...)` +// +// The following flags are currently supported: +// +// omitempty Only include the field if it's not set to the zero +// value for the type or to empty slices or maps. +// Zero valued structs will be omitted if all their public +// fields are zero, unless they implement an IsZero +// method (see the IsZeroer interface type), in which +// case the field will be excluded if IsZero returns true. +// +// flow Marshal using a flow style (useful for structs, +// sequences and maps). +// +// inline Inline the field, which must be a struct or a map, +// causing all of its fields or keys to be processed as if +// they were part of the outer struct. For maps, keys must +// not conflict with the yaml keys of other struct fields. +// +// In addition, if the key is "-", the field is ignored. +// +// For example: +// +// type T struct { +// F int `yaml:"a,omitempty"` +// B int +// } +// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n" +// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n" +// +func Marshal(in interface{}) (out []byte, err error) { + defer handleErr(&err) + e := newEncoder() + defer e.destroy() + e.marshalDoc("", reflect.ValueOf(in)) + e.finish() + out = e.out + return +} + +// An Encoder writes YAML values to an output stream. +type Encoder struct { + encoder *encoder +} + +// NewEncoder returns a new encoder that writes to w. +// The Encoder should be closed after use to flush all data +// to w. +func NewEncoder(w io.Writer) *Encoder { + return &Encoder{ + encoder: newEncoderWithWriter(w), + } +} + +// Encode writes the YAML encoding of v to the stream. +// If multiple items are encoded to the stream, the +// second and subsequent document will be preceded +// with a "---" document separator, but the first will not. +// +// See the documentation for Marshal for details about the conversion of Go +// values to YAML. +func (e *Encoder) Encode(v interface{}) (err error) { + defer handleErr(&err) + e.encoder.marshalDoc("", reflect.ValueOf(v)) + return nil +} + +// Encode encodes value v and stores its representation in n. +// +// See the documentation for Marshal for details about the +// conversion of Go values into YAML. +func (n *Node) Encode(v interface{}) (err error) { + defer handleErr(&err) + e := newEncoder() + defer e.destroy() + e.marshalDoc("", reflect.ValueOf(v)) + e.finish() + p := newParser(e.out) + p.textless = true + defer p.destroy() + doc := p.parse() + *n = *doc.Content[0] + return nil +} + +// SetIndent changes the used indentation used when encoding. +func (e *Encoder) SetIndent(spaces int) { + if spaces < 0 { + panic("yaml: cannot indent to a negative number of spaces") + } + e.encoder.indent = spaces +} + +// CompactSeqIndent makes it so that '- ' is considered part of the indentation. +func (e *Encoder) CompactSeqIndent() { + e.encoder.emitter.compact_sequence_indent = true +} + +// DefaultSeqIndent makes it so that '- ' is not considered part of the indentation. +func (e *Encoder) DefaultSeqIndent() { + e.encoder.emitter.compact_sequence_indent = false +} + +// Close closes the encoder by writing any remaining data. +// It does not write a stream terminating string "...". +func (e *Encoder) Close() (err error) { + defer handleErr(&err) + e.encoder.finish() + return nil +} + +func handleErr(err *error) { + if v := recover(); v != nil { + if e, ok := v.(yamlError); ok { + *err = e.err + } else { + panic(v) + } + } +} + +type yamlError struct { + err error +} + +func fail(err error) { + panic(yamlError{err}) +} + +func failf(format string, args ...interface{}) { + panic(yamlError{fmt.Errorf("yaml: "+format, args...)}) +} + +// A TypeError is returned by Unmarshal when one or more fields in +// the YAML document cannot be properly decoded into the requested +// types. When this error is returned, the value is still +// unmarshaled partially. +type TypeError struct { + Errors []string +} + +func (e *TypeError) Error() string { + return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n ")) +} + +type Kind uint32 + +const ( + DocumentNode Kind = 1 << iota + SequenceNode + MappingNode + ScalarNode + AliasNode +) + +type Style uint32 + +const ( + TaggedStyle Style = 1 << iota + DoubleQuotedStyle + SingleQuotedStyle + LiteralStyle + FoldedStyle + FlowStyle +) + +// Node represents an element in the YAML document hierarchy. While documents +// are typically encoded and decoded into higher level types, such as structs +// and maps, Node is an intermediate representation that allows detailed +// control over the content being decoded or encoded. +// +// It's worth noting that although Node offers access into details such as +// line numbers, colums, and comments, the content when re-encoded will not +// have its original textual representation preserved. An effort is made to +// render the data plesantly, and to preserve comments near the data they +// describe, though. +// +// Values that make use of the Node type interact with the yaml package in the +// same way any other type would do, by encoding and decoding yaml data +// directly or indirectly into them. +// +// For example: +// +// var person struct { +// Name string +// Address yaml.Node +// } +// err := yaml.Unmarshal(data, &person) +// +// Or by itself: +// +// var person Node +// err := yaml.Unmarshal(data, &person) +// +type Node struct { + // Kind defines whether the node is a document, a mapping, a sequence, + // a scalar value, or an alias to another node. The specific data type of + // scalar nodes may be obtained via the ShortTag and LongTag methods. + Kind Kind + + // Style allows customizing the apperance of the node in the tree. + Style Style + + // Tag holds the YAML tag defining the data type for the value. + // When decoding, this field will always be set to the resolved tag, + // even when it wasn't explicitly provided in the YAML content. + // When encoding, if this field is unset the value type will be + // implied from the node properties, and if it is set, it will only + // be serialized into the representation if TaggedStyle is used or + // the implicit tag diverges from the provided one. + Tag string + + // Value holds the unescaped and unquoted represenation of the value. + Value string + + // Anchor holds the anchor name for this node, which allows aliases to point to it. + Anchor string + + // Alias holds the node that this alias points to. Only valid when Kind is AliasNode. + Alias *Node + + // Content holds contained nodes for documents, mappings, and sequences. + Content []*Node + + // HeadComment holds any comments in the lines preceding the node and + // not separated by an empty line. + HeadComment string + + // LineComment holds any comments at the end of the line where the node is in. + LineComment string + + // FootComment holds any comments following the node and before empty lines. + FootComment string + + // Line and Column hold the node position in the decoded YAML text. + // These fields are not respected when encoding the node. + Line int + Column int +} + +// IsZero returns whether the node has all of its fields unset. +func (n *Node) IsZero() bool { + return n.Kind == 0 && n.Style == 0 && n.Tag == "" && n.Value == "" && n.Anchor == "" && n.Alias == nil && n.Content == nil && + n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0 +} + + +// LongTag returns the long form of the tag that indicates the data type for +// the node. If the Tag field isn't explicitly defined, one will be computed +// based on the node properties. +func (n *Node) LongTag() string { + return longTag(n.ShortTag()) +} + +// ShortTag returns the short form of the YAML tag that indicates data type for +// the node. If the Tag field isn't explicitly defined, one will be computed +// based on the node properties. +func (n *Node) ShortTag() string { + if n.indicatedString() { + return strTag + } + if n.Tag == "" || n.Tag == "!" { + switch n.Kind { + case MappingNode: + return mapTag + case SequenceNode: + return seqTag + case AliasNode: + if n.Alias != nil { + return n.Alias.ShortTag() + } + case ScalarNode: + tag, _ := resolve("", n.Value) + return tag + case 0: + // Special case to make the zero value convenient. + if n.IsZero() { + return nullTag + } + } + return "" + } + return shortTag(n.Tag) +} + +func (n *Node) indicatedString() bool { + return n.Kind == ScalarNode && + (shortTag(n.Tag) == strTag || + (n.Tag == "" || n.Tag == "!") && n.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0) +} + +// SetString is a convenience function that sets the node to a string value +// and defines its style in a pleasant way depending on its content. +func (n *Node) SetString(s string) { + n.Kind = ScalarNode + if utf8.ValidString(s) { + n.Value = s + n.Tag = strTag + } else { + n.Value = encodeBase64(s) + n.Tag = binaryTag + } + if strings.Contains(n.Value, "\n") { + n.Style = LiteralStyle + } +} + +// -------------------------------------------------------------------------- +// Maintain a mapping of keys to structure field indexes + +// The code in this section was copied from mgo/bson. + +// structInfo holds details for the serialization of fields of +// a given struct. +type structInfo struct { + FieldsMap map[string]fieldInfo + FieldsList []fieldInfo + + // InlineMap is the number of the field in the struct that + // contains an ,inline map, or -1 if there's none. + InlineMap int + + // InlineUnmarshalers holds indexes to inlined fields that + // contain unmarshaler values. + InlineUnmarshalers [][]int +} + +type fieldInfo struct { + Key string + Num int + OmitEmpty bool + Flow bool + // Id holds the unique field identifier, so we can cheaply + // check for field duplicates without maintaining an extra map. + Id int + + // Inline holds the field index if the field is part of an inlined struct. + Inline []int +} + +var structMap = make(map[reflect.Type]*structInfo) +var fieldMapMutex sync.RWMutex +var unmarshalerType reflect.Type + +func init() { + var v Unmarshaler + unmarshalerType = reflect.ValueOf(&v).Elem().Type() +} + +func getStructInfo(st reflect.Type) (*structInfo, error) { + fieldMapMutex.RLock() + sinfo, found := structMap[st] + fieldMapMutex.RUnlock() + if found { + return sinfo, nil + } + + n := st.NumField() + fieldsMap := make(map[string]fieldInfo) + fieldsList := make([]fieldInfo, 0, n) + inlineMap := -1 + inlineUnmarshalers := [][]int(nil) + for i := 0; i != n; i++ { + field := st.Field(i) + if field.PkgPath != "" && !field.Anonymous { + continue // Private field + } + + info := fieldInfo{Num: i} + + tag := field.Tag.Get("yaml") + if tag == "" && strings.Index(string(field.Tag), ":") < 0 { + tag = string(field.Tag) + } + if tag == "-" { + continue + } + + inline := false + fields := strings.Split(tag, ",") + if len(fields) > 1 { + for _, flag := range fields[1:] { + switch flag { + case "omitempty": + info.OmitEmpty = true + case "flow": + info.Flow = true + case "inline": + inline = true + default: + return nil, errors.New(fmt.Sprintf("unsupported flag %q in tag %q of type %s", flag, tag, st)) + } + } + tag = fields[0] + } + + if inline { + switch field.Type.Kind() { + case reflect.Map: + if inlineMap >= 0 { + return nil, errors.New("multiple ,inline maps in struct " + st.String()) + } + if field.Type.Key() != reflect.TypeOf("") { + return nil, errors.New("option ,inline needs a map with string keys in struct " + st.String()) + } + inlineMap = info.Num + case reflect.Struct, reflect.Ptr: + ftype := field.Type + for ftype.Kind() == reflect.Ptr { + ftype = ftype.Elem() + } + if ftype.Kind() != reflect.Struct { + return nil, errors.New("option ,inline may only be used on a struct or map field") + } + if reflect.PtrTo(ftype).Implements(unmarshalerType) { + inlineUnmarshalers = append(inlineUnmarshalers, []int{i}) + } else { + sinfo, err := getStructInfo(ftype) + if err != nil { + return nil, err + } + for _, index := range sinfo.InlineUnmarshalers { + inlineUnmarshalers = append(inlineUnmarshalers, append([]int{i}, index...)) + } + for _, finfo := range sinfo.FieldsList { + if _, found := fieldsMap[finfo.Key]; found { + msg := "duplicated key '" + finfo.Key + "' in struct " + st.String() + return nil, errors.New(msg) + } + if finfo.Inline == nil { + finfo.Inline = []int{i, finfo.Num} + } else { + finfo.Inline = append([]int{i}, finfo.Inline...) + } + finfo.Id = len(fieldsList) + fieldsMap[finfo.Key] = finfo + fieldsList = append(fieldsList, finfo) + } + } + default: + return nil, errors.New("option ,inline may only be used on a struct or map field") + } + continue + } + + if tag != "" { + info.Key = tag + } else { + info.Key = strings.ToLower(field.Name) + } + + if _, found = fieldsMap[info.Key]; found { + msg := "duplicated key '" + info.Key + "' in struct " + st.String() + return nil, errors.New(msg) + } + + info.Id = len(fieldsList) + fieldsList = append(fieldsList, info) + fieldsMap[info.Key] = info + } + + sinfo = &structInfo{ + FieldsMap: fieldsMap, + FieldsList: fieldsList, + InlineMap: inlineMap, + InlineUnmarshalers: inlineUnmarshalers, + } + + fieldMapMutex.Lock() + structMap[st] = sinfo + fieldMapMutex.Unlock() + return sinfo, nil +} + +// IsZeroer is used to check whether an object is zero to +// determine whether it should be omitted when marshaling +// with the omitempty flag. One notable implementation +// is time.Time. +type IsZeroer interface { + IsZero() bool +} + +func isZero(v reflect.Value) bool { + kind := v.Kind() + if z, ok := v.Interface().(IsZeroer); ok { + if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() { + return true + } + return z.IsZero() + } + switch kind { + case reflect.String: + return len(v.String()) == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + case reflect.Slice: + return v.Len() == 0 + case reflect.Map: + return v.Len() == 0 + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Struct: + vt := v.Type() + for i := v.NumField() - 1; i >= 0; i-- { + if vt.Field(i).PkgPath != "" { + continue // Private field + } + if !isZero(v.Field(i)) { + return false + } + } + return true + } + return false +} diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/yamlh.go b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/yamlh.go new file mode 100644 index 000000000..40c74de49 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/yamlh.go @@ -0,0 +1,809 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// Copyright (c) 2006-2010 Kirill Simonov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package yaml + +import ( + "fmt" + "io" +) + +// The version directive data. +type yaml_version_directive_t struct { + major int8 // The major version number. + minor int8 // The minor version number. +} + +// The tag directive data. +type yaml_tag_directive_t struct { + handle []byte // The tag handle. + prefix []byte // The tag prefix. +} + +type yaml_encoding_t int + +// The stream encoding. +const ( + // Let the parser choose the encoding. + yaml_ANY_ENCODING yaml_encoding_t = iota + + yaml_UTF8_ENCODING // The default UTF-8 encoding. + yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM. + yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM. +) + +type yaml_break_t int + +// Line break types. +const ( + // Let the parser choose the break type. + yaml_ANY_BREAK yaml_break_t = iota + + yaml_CR_BREAK // Use CR for line breaks (Mac style). + yaml_LN_BREAK // Use LN for line breaks (Unix style). + yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style). +) + +type yaml_error_type_t int + +// Many bad things could happen with the parser and emitter. +const ( + // No error is produced. + yaml_NO_ERROR yaml_error_type_t = iota + + yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory. + yaml_READER_ERROR // Cannot read or decode the input stream. + yaml_SCANNER_ERROR // Cannot scan the input stream. + yaml_PARSER_ERROR // Cannot parse the input stream. + yaml_COMPOSER_ERROR // Cannot compose a YAML document. + yaml_WRITER_ERROR // Cannot write to the output stream. + yaml_EMITTER_ERROR // Cannot emit a YAML stream. +) + +// The pointer position. +type yaml_mark_t struct { + index int // The position index. + line int // The position line. + column int // The position column. +} + +// Node Styles + +type yaml_style_t int8 + +type yaml_scalar_style_t yaml_style_t + +// Scalar styles. +const ( + // Let the emitter choose the style. + yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = 0 + + yaml_PLAIN_SCALAR_STYLE yaml_scalar_style_t = 1 << iota // The plain scalar style. + yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style. + yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style. + yaml_LITERAL_SCALAR_STYLE // The literal scalar style. + yaml_FOLDED_SCALAR_STYLE // The folded scalar style. +) + +type yaml_sequence_style_t yaml_style_t + +// Sequence styles. +const ( + // Let the emitter choose the style. + yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota + + yaml_BLOCK_SEQUENCE_STYLE // The block sequence style. + yaml_FLOW_SEQUENCE_STYLE // The flow sequence style. +) + +type yaml_mapping_style_t yaml_style_t + +// Mapping styles. +const ( + // Let the emitter choose the style. + yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota + + yaml_BLOCK_MAPPING_STYLE // The block mapping style. + yaml_FLOW_MAPPING_STYLE // The flow mapping style. +) + +// Tokens + +type yaml_token_type_t int + +// Token types. +const ( + // An empty token. + yaml_NO_TOKEN yaml_token_type_t = iota + + yaml_STREAM_START_TOKEN // A STREAM-START token. + yaml_STREAM_END_TOKEN // A STREAM-END token. + + yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token. + yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token. + yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token. + yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token. + + yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token. + yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token. + yaml_BLOCK_END_TOKEN // A BLOCK-END token. + + yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token. + yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token. + yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token. + yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token. + + yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token. + yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token. + yaml_KEY_TOKEN // A KEY token. + yaml_VALUE_TOKEN // A VALUE token. + + yaml_ALIAS_TOKEN // An ALIAS token. + yaml_ANCHOR_TOKEN // An ANCHOR token. + yaml_TAG_TOKEN // A TAG token. + yaml_SCALAR_TOKEN // A SCALAR token. +) + +func (tt yaml_token_type_t) String() string { + switch tt { + case yaml_NO_TOKEN: + return "yaml_NO_TOKEN" + case yaml_STREAM_START_TOKEN: + return "yaml_STREAM_START_TOKEN" + case yaml_STREAM_END_TOKEN: + return "yaml_STREAM_END_TOKEN" + case yaml_VERSION_DIRECTIVE_TOKEN: + return "yaml_VERSION_DIRECTIVE_TOKEN" + case yaml_TAG_DIRECTIVE_TOKEN: + return "yaml_TAG_DIRECTIVE_TOKEN" + case yaml_DOCUMENT_START_TOKEN: + return "yaml_DOCUMENT_START_TOKEN" + case yaml_DOCUMENT_END_TOKEN: + return "yaml_DOCUMENT_END_TOKEN" + case yaml_BLOCK_SEQUENCE_START_TOKEN: + return "yaml_BLOCK_SEQUENCE_START_TOKEN" + case yaml_BLOCK_MAPPING_START_TOKEN: + return "yaml_BLOCK_MAPPING_START_TOKEN" + case yaml_BLOCK_END_TOKEN: + return "yaml_BLOCK_END_TOKEN" + case yaml_FLOW_SEQUENCE_START_TOKEN: + return "yaml_FLOW_SEQUENCE_START_TOKEN" + case yaml_FLOW_SEQUENCE_END_TOKEN: + return "yaml_FLOW_SEQUENCE_END_TOKEN" + case yaml_FLOW_MAPPING_START_TOKEN: + return "yaml_FLOW_MAPPING_START_TOKEN" + case yaml_FLOW_MAPPING_END_TOKEN: + return "yaml_FLOW_MAPPING_END_TOKEN" + case yaml_BLOCK_ENTRY_TOKEN: + return "yaml_BLOCK_ENTRY_TOKEN" + case yaml_FLOW_ENTRY_TOKEN: + return "yaml_FLOW_ENTRY_TOKEN" + case yaml_KEY_TOKEN: + return "yaml_KEY_TOKEN" + case yaml_VALUE_TOKEN: + return "yaml_VALUE_TOKEN" + case yaml_ALIAS_TOKEN: + return "yaml_ALIAS_TOKEN" + case yaml_ANCHOR_TOKEN: + return "yaml_ANCHOR_TOKEN" + case yaml_TAG_TOKEN: + return "yaml_TAG_TOKEN" + case yaml_SCALAR_TOKEN: + return "yaml_SCALAR_TOKEN" + } + return "" +} + +// The token structure. +type yaml_token_t struct { + // The token type. + typ yaml_token_type_t + + // The start/end of the token. + start_mark, end_mark yaml_mark_t + + // The stream encoding (for yaml_STREAM_START_TOKEN). + encoding yaml_encoding_t + + // The alias/anchor/scalar value or tag/tag directive handle + // (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN). + value []byte + + // The tag suffix (for yaml_TAG_TOKEN). + suffix []byte + + // The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN). + prefix []byte + + // The scalar style (for yaml_SCALAR_TOKEN). + style yaml_scalar_style_t + + // The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN). + major, minor int8 +} + +// Events + +type yaml_event_type_t int8 + +// Event types. +const ( + // An empty event. + yaml_NO_EVENT yaml_event_type_t = iota + + yaml_STREAM_START_EVENT // A STREAM-START event. + yaml_STREAM_END_EVENT // A STREAM-END event. + yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event. + yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event. + yaml_ALIAS_EVENT // An ALIAS event. + yaml_SCALAR_EVENT // A SCALAR event. + yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event. + yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event. + yaml_MAPPING_START_EVENT // A MAPPING-START event. + yaml_MAPPING_END_EVENT // A MAPPING-END event. + yaml_TAIL_COMMENT_EVENT +) + +var eventStrings = []string{ + yaml_NO_EVENT: "none", + yaml_STREAM_START_EVENT: "stream start", + yaml_STREAM_END_EVENT: "stream end", + yaml_DOCUMENT_START_EVENT: "document start", + yaml_DOCUMENT_END_EVENT: "document end", + yaml_ALIAS_EVENT: "alias", + yaml_SCALAR_EVENT: "scalar", + yaml_SEQUENCE_START_EVENT: "sequence start", + yaml_SEQUENCE_END_EVENT: "sequence end", + yaml_MAPPING_START_EVENT: "mapping start", + yaml_MAPPING_END_EVENT: "mapping end", + yaml_TAIL_COMMENT_EVENT: "tail comment", +} + +func (e yaml_event_type_t) String() string { + if e < 0 || int(e) >= len(eventStrings) { + return fmt.Sprintf("unknown event %d", e) + } + return eventStrings[e] +} + +// The event structure. +type yaml_event_t struct { + + // The event type. + typ yaml_event_type_t + + // The start and end of the event. + start_mark, end_mark yaml_mark_t + + // The document encoding (for yaml_STREAM_START_EVENT). + encoding yaml_encoding_t + + // The version directive (for yaml_DOCUMENT_START_EVENT). + version_directive *yaml_version_directive_t + + // The list of tag directives (for yaml_DOCUMENT_START_EVENT). + tag_directives []yaml_tag_directive_t + + // The comments + head_comment []byte + line_comment []byte + foot_comment []byte + tail_comment []byte + + // The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT). + anchor []byte + + // The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). + tag []byte + + // The scalar value (for yaml_SCALAR_EVENT). + value []byte + + // Is the document start/end indicator implicit, or the tag optional? + // (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT). + implicit bool + + // Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT). + quoted_implicit bool + + // The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). + style yaml_style_t +} + +func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) } +func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) } +func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) } + +// Nodes + +const ( + yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null. + yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false. + yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values. + yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values. + yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values. + yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values. + + yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences. + yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping. + + // Not in original libyaml. + yaml_BINARY_TAG = "tag:yaml.org,2002:binary" + yaml_MERGE_TAG = "tag:yaml.org,2002:merge" + + yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str. + yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq. + yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map. +) + +type yaml_node_type_t int + +// Node types. +const ( + // An empty node. + yaml_NO_NODE yaml_node_type_t = iota + + yaml_SCALAR_NODE // A scalar node. + yaml_SEQUENCE_NODE // A sequence node. + yaml_MAPPING_NODE // A mapping node. +) + +// An element of a sequence node. +type yaml_node_item_t int + +// An element of a mapping node. +type yaml_node_pair_t struct { + key int // The key of the element. + value int // The value of the element. +} + +// The node structure. +type yaml_node_t struct { + typ yaml_node_type_t // The node type. + tag []byte // The node tag. + + // The node data. + + // The scalar parameters (for yaml_SCALAR_NODE). + scalar struct { + value []byte // The scalar value. + length int // The length of the scalar value. + style yaml_scalar_style_t // The scalar style. + } + + // The sequence parameters (for YAML_SEQUENCE_NODE). + sequence struct { + items_data []yaml_node_item_t // The stack of sequence items. + style yaml_sequence_style_t // The sequence style. + } + + // The mapping parameters (for yaml_MAPPING_NODE). + mapping struct { + pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value). + pairs_start *yaml_node_pair_t // The beginning of the stack. + pairs_end *yaml_node_pair_t // The end of the stack. + pairs_top *yaml_node_pair_t // The top of the stack. + style yaml_mapping_style_t // The mapping style. + } + + start_mark yaml_mark_t // The beginning of the node. + end_mark yaml_mark_t // The end of the node. + +} + +// The document structure. +type yaml_document_t struct { + + // The document nodes. + nodes []yaml_node_t + + // The version directive. + version_directive *yaml_version_directive_t + + // The list of tag directives. + tag_directives_data []yaml_tag_directive_t + tag_directives_start int // The beginning of the tag directives list. + tag_directives_end int // The end of the tag directives list. + + start_implicit int // Is the document start indicator implicit? + end_implicit int // Is the document end indicator implicit? + + // The start/end of the document. + start_mark, end_mark yaml_mark_t +} + +// The prototype of a read handler. +// +// The read handler is called when the parser needs to read more bytes from the +// source. The handler should write not more than size bytes to the buffer. +// The number of written bytes should be set to the size_read variable. +// +// [in,out] data A pointer to an application data specified by +// yaml_parser_set_input(). +// [out] buffer The buffer to write the data from the source. +// [in] size The size of the buffer. +// [out] size_read The actual number of bytes read from the source. +// +// On success, the handler should return 1. If the handler failed, +// the returned value should be 0. On EOF, the handler should set the +// size_read to 0 and return 1. +type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error) + +// This structure holds information about a potential simple key. +type yaml_simple_key_t struct { + possible bool // Is a simple key possible? + required bool // Is a simple key required? + token_number int // The number of the token. + mark yaml_mark_t // The position mark. +} + +// The states of the parser. +type yaml_parser_state_t int + +const ( + yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota + + yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document. + yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START. + yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document. + yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END. + yaml_PARSE_BLOCK_NODE_STATE // Expect a block node. + yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence. + yaml_PARSE_FLOW_NODE_STATE // Expect a flow node. + yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence. + yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence. + yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence. + yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. + yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key. + yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value. + yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry. + yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. + yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. + yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. + yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping. + yaml_PARSE_END_STATE // Expect nothing. +) + +func (ps yaml_parser_state_t) String() string { + switch ps { + case yaml_PARSE_STREAM_START_STATE: + return "yaml_PARSE_STREAM_START_STATE" + case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: + return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE" + case yaml_PARSE_DOCUMENT_START_STATE: + return "yaml_PARSE_DOCUMENT_START_STATE" + case yaml_PARSE_DOCUMENT_CONTENT_STATE: + return "yaml_PARSE_DOCUMENT_CONTENT_STATE" + case yaml_PARSE_DOCUMENT_END_STATE: + return "yaml_PARSE_DOCUMENT_END_STATE" + case yaml_PARSE_BLOCK_NODE_STATE: + return "yaml_PARSE_BLOCK_NODE_STATE" + case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: + return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE" + case yaml_PARSE_FLOW_NODE_STATE: + return "yaml_PARSE_FLOW_NODE_STATE" + case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: + return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE" + case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: + return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE" + case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: + return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE" + case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: + return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE" + case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: + return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE" + case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: + return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE" + case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE" + case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: + return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE" + case yaml_PARSE_FLOW_MAPPING_KEY_STATE: + return "yaml_PARSE_FLOW_MAPPING_KEY_STATE" + case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: + return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE" + case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: + return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE" + case yaml_PARSE_END_STATE: + return "yaml_PARSE_END_STATE" + } + return "" +} + +// This structure holds aliases data. +type yaml_alias_data_t struct { + anchor []byte // The anchor. + index int // The node id. + mark yaml_mark_t // The anchor mark. +} + +// The parser structure. +// +// All members are internal. Manage the structure using the +// yaml_parser_ family of functions. +type yaml_parser_t struct { + + // Error handling + + error yaml_error_type_t // Error type. + + problem string // Error description. + + // The byte about which the problem occurred. + problem_offset int + problem_value int + problem_mark yaml_mark_t + + // The error context. + context string + context_mark yaml_mark_t + + // Reader stuff + + read_handler yaml_read_handler_t // Read handler. + + input_reader io.Reader // File input data. + input []byte // String input data. + input_pos int + + eof bool // EOF flag + + buffer []byte // The working buffer. + buffer_pos int // The current position of the buffer. + + unread int // The number of unread characters in the buffer. + + newlines int // The number of line breaks since last non-break/non-blank character + + raw_buffer []byte // The raw buffer. + raw_buffer_pos int // The current position of the buffer. + + encoding yaml_encoding_t // The input encoding. + + offset int // The offset of the current position (in bytes). + mark yaml_mark_t // The mark of the current position. + + // Comments + + head_comment []byte // The current head comments + line_comment []byte // The current line comments + foot_comment []byte // The current foot comments + tail_comment []byte // Foot comment that happens at the end of a block. + stem_comment []byte // Comment in item preceding a nested structure (list inside list item, etc) + + comments []yaml_comment_t // The folded comments for all parsed tokens + comments_head int + + // Scanner stuff + + stream_start_produced bool // Have we started to scan the input stream? + stream_end_produced bool // Have we reached the end of the input stream? + + flow_level int // The number of unclosed '[' and '{' indicators. + + tokens []yaml_token_t // The tokens queue. + tokens_head int // The head of the tokens queue. + tokens_parsed int // The number of tokens fetched from the queue. + token_available bool // Does the tokens queue contain a token ready for dequeueing. + + indent int // The current indentation level. + indents []int // The indentation levels stack. + + simple_key_allowed bool // May a simple key occur at the current position? + simple_keys []yaml_simple_key_t // The stack of simple keys. + simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number + + // Parser stuff + + state yaml_parser_state_t // The current parser state. + states []yaml_parser_state_t // The parser states stack. + marks []yaml_mark_t // The stack of marks. + tag_directives []yaml_tag_directive_t // The list of TAG directives. + + // Dumper stuff + + aliases []yaml_alias_data_t // The alias data. + + document *yaml_document_t // The currently parsed document. +} + +type yaml_comment_t struct { + + scan_mark yaml_mark_t // Position where scanning for comments started + token_mark yaml_mark_t // Position after which tokens will be associated with this comment + start_mark yaml_mark_t // Position of '#' comment mark + end_mark yaml_mark_t // Position where comment terminated + + head []byte + line []byte + foot []byte +} + +// Emitter Definitions + +// The prototype of a write handler. +// +// The write handler is called when the emitter needs to flush the accumulated +// characters to the output. The handler should write @a size bytes of the +// @a buffer to the output. +// +// @param[in,out] data A pointer to an application data specified by +// yaml_emitter_set_output(). +// @param[in] buffer The buffer with bytes to be written. +// @param[in] size The size of the buffer. +// +// @returns On success, the handler should return @c 1. If the handler failed, +// the returned value should be @c 0. +// +type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error + +type yaml_emitter_state_t int + +// The emitter states. +const ( + // Expect STREAM-START. + yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota + + yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END. + yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END. + yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document. + yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END. + yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence. + yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE // Expect the next item of a flow sequence, with the comma already written out + yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence. + yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. + yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE // Expect the next key of a flow mapping, with the comma already written out + yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. + yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping. + yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. + yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence. + yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence. + yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. + yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping. + yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping. + yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping. + yaml_EMIT_END_STATE // Expect nothing. +) + +// The emitter structure. +// +// All members are internal. Manage the structure using the @c yaml_emitter_ +// family of functions. +type yaml_emitter_t struct { + + // Error handling + + error yaml_error_type_t // Error type. + problem string // Error description. + + // Writer stuff + + write_handler yaml_write_handler_t // Write handler. + + output_buffer *[]byte // String output data. + output_writer io.Writer // File output data. + + buffer []byte // The working buffer. + buffer_pos int // The current position of the buffer. + + raw_buffer []byte // The raw buffer. + raw_buffer_pos int // The current position of the buffer. + + encoding yaml_encoding_t // The stream encoding. + + // Emitter stuff + + canonical bool // If the output is in the canonical style? + best_indent int // The number of indentation spaces. + best_width int // The preferred width of the output lines. + unicode bool // Allow unescaped non-ASCII characters? + line_break yaml_break_t // The preferred line break. + + state yaml_emitter_state_t // The current emitter state. + states []yaml_emitter_state_t // The stack of states. + + events []yaml_event_t // The event queue. + events_head int // The head of the event queue. + + indents []int // The stack of indentation levels. + + tag_directives []yaml_tag_directive_t // The list of tag directives. + + indent int // The current indentation level. + + compact_sequence_indent bool // Is '- ' is considered part of the indentation for sequence elements? + + flow_level int // The current flow level. + + root_context bool // Is it the document root context? + sequence_context bool // Is it a sequence context? + mapping_context bool // Is it a mapping context? + simple_key_context bool // Is it a simple mapping key context? + + line int // The current line. + column int // The current column. + whitespace bool // If the last character was a whitespace? + indention bool // If the last character was an indentation character (' ', '-', '?', ':')? + open_ended bool // If an explicit document end is required? + + space_above bool // Is there's an empty line above? + foot_indent int // The indent used to write the foot comment above, or -1 if none. + + // Anchor analysis. + anchor_data struct { + anchor []byte // The anchor value. + alias bool // Is it an alias? + } + + // Tag analysis. + tag_data struct { + handle []byte // The tag handle. + suffix []byte // The tag suffix. + } + + // Scalar analysis. + scalar_data struct { + value []byte // The scalar value. + multiline bool // Does the scalar contain line breaks? + flow_plain_allowed bool // Can the scalar be expessed in the flow plain style? + block_plain_allowed bool // Can the scalar be expressed in the block plain style? + single_quoted_allowed bool // Can the scalar be expressed in the single quoted style? + block_allowed bool // Can the scalar be expressed in the literal or folded styles? + style yaml_scalar_style_t // The output style. + } + + // Comments + head_comment []byte + line_comment []byte + foot_comment []byte + tail_comment []byte + + key_line_comment []byte + + // Dumper stuff + + opened bool // If the stream was already opened? + closed bool // If the stream was already closed? + + // The information associated with the document nodes. + anchors *struct { + references int // The number of references. + anchor int // The anchor id. + serialized bool // If the node has been emitted? + } + + last_anchor_id int // The last assigned anchor id. + + document *yaml_document_t // The currently emitted document. +} diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/yamlprivateh.go b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/yamlprivateh.go new file mode 100644 index 000000000..e88f9c54a --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml/yamlprivateh.go @@ -0,0 +1,198 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// Copyright (c) 2006-2010 Kirill Simonov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package yaml + +const ( + // The size of the input raw buffer. + input_raw_buffer_size = 512 + + // The size of the input buffer. + // It should be possible to decode the whole raw buffer. + input_buffer_size = input_raw_buffer_size * 3 + + // The size of the output buffer. + output_buffer_size = 128 + + // The size of the output raw buffer. + // It should be possible to encode the whole output buffer. + output_raw_buffer_size = (output_buffer_size*2 + 2) + + // The size of other stacks and queues. + initial_stack_size = 16 + initial_queue_size = 16 + initial_string_size = 16 +) + +// Check if the character at the specified position is an alphabetical +// character, a digit, '_', or '-'. +func is_alpha(b []byte, i int) bool { + return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-' +} + +// Check if the character at the specified position is a digit. +func is_digit(b []byte, i int) bool { + return b[i] >= '0' && b[i] <= '9' +} + +// Get the value of a digit. +func as_digit(b []byte, i int) int { + return int(b[i]) - '0' +} + +// Check if the character at the specified position is a hex-digit. +func is_hex(b []byte, i int) bool { + return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f' +} + +// Get the value of a hex-digit. +func as_hex(b []byte, i int) int { + bi := b[i] + if bi >= 'A' && bi <= 'F' { + return int(bi) - 'A' + 10 + } + if bi >= 'a' && bi <= 'f' { + return int(bi) - 'a' + 10 + } + return int(bi) - '0' +} + +// Check if the character is ASCII. +func is_ascii(b []byte, i int) bool { + return b[i] <= 0x7F +} + +// Check if the character at the start of the buffer can be printed unescaped. +func is_printable(b []byte, i int) bool { + return ((b[i] == 0x0A) || // . == #x0A + (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E + (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF + (b[i] > 0xC2 && b[i] < 0xED) || + (b[i] == 0xED && b[i+1] < 0xA0) || + (b[i] == 0xEE) || + (b[i] == 0xEF && // #xE000 <= . <= #xFFFD + !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF + !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF)))) +} + +// Check if the character at the specified position is NUL. +func is_z(b []byte, i int) bool { + return b[i] == 0x00 +} + +// Check if the beginning of the buffer is a BOM. +func is_bom(b []byte, i int) bool { + return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF +} + +// Check if the character at the specified position is space. +func is_space(b []byte, i int) bool { + return b[i] == ' ' +} + +// Check if the character at the specified position is tab. +func is_tab(b []byte, i int) bool { + return b[i] == '\t' +} + +// Check if the character at the specified position is blank (space or tab). +func is_blank(b []byte, i int) bool { + //return is_space(b, i) || is_tab(b, i) + return b[i] == ' ' || b[i] == '\t' +} + +// Check if the character at the specified position is a line break. +func is_break(b []byte, i int) bool { + return (b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029) +} + +func is_crlf(b []byte, i int) bool { + return b[i] == '\r' && b[i+1] == '\n' +} + +// Check if the character is a line break or NUL. +func is_breakz(b []byte, i int) bool { + //return is_break(b, i) || is_z(b, i) + return ( + // is_break: + b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) + // is_z: + b[i] == 0) +} + +// Check if the character is a line break, space, or NUL. +func is_spacez(b []byte, i int) bool { + //return is_space(b, i) || is_breakz(b, i) + return ( + // is_space: + b[i] == ' ' || + // is_breakz: + b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) + b[i] == 0) +} + +// Check if the character is a line break, space, tab, or NUL. +func is_blankz(b []byte, i int) bool { + //return is_blank(b, i) || is_breakz(b, i) + return ( + // is_blank: + b[i] == ' ' || b[i] == '\t' || + // is_breakz: + b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) + b[i] == 0) +} + +// Determine the width of the character. +func width(b byte) int { + // Don't replace these by a switch without first + // confirming that it is being inlined. + if b&0x80 == 0x00 { + return 1 + } + if b&0xE0 == 0xC0 { + return 2 + } + if b&0xF0 == 0xE0 { + return 3 + } + if b&0xF8 == 0xF0 { + return 4 + } + return 0 + +} diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/kio/byteio_writer.go b/vendor/sigs.k8s.io/kustomize/kyaml/kio/byteio_writer.go index 84097f108..a208f52bb 100644 --- a/vendor/sigs.k8s.io/kustomize/kyaml/kio/byteio_writer.go +++ b/vendor/sigs.k8s.io/kustomize/kyaml/kio/byteio_writer.go @@ -6,13 +6,16 @@ package kio import ( "encoding/json" "io" - + "path/filepath" "sigs.k8s.io/kustomize/kyaml/errors" "sigs.k8s.io/kustomize/kyaml/kio/kioutil" "sigs.k8s.io/kustomize/kyaml/yaml" ) -// Writer writes ResourceNodes to bytes. +// ByteWriter writes ResourceNodes to bytes. Generally YAML encoding will be used but in the special +// case of writing a single, bare yaml.RNode that has a kioutil.PathAnnotation indicating that the +// target is a JSON file JSON encoding is used. See shouldJSONEncodeSingleBareNode below for more +// information. type ByteWriter struct { // Writer is where ResourceNodes are encoded. Writer io.Writer @@ -47,16 +50,18 @@ type ByteWriter struct { var _ Writer = ByteWriter{} -func (w ByteWriter) Write(nodes []*yaml.RNode) error { - yaml.DoSerializationHacksOnNodes(nodes) +func (w ByteWriter) Write(inputNodes []*yaml.RNode) error { + // Copy the nodes to prevent writer from mutating the original nodes. + nodes := copyRNodes(inputNodes) if w.Sort { if err := kioutil.SortNodes(nodes); err != nil { return errors.Wrap(err) } } - encoder := yaml.NewEncoder(w.Writer) - defer encoder.Close() + // Even though we use the this value further down we must check this before removing annotations + jsonEncodeSingleBareNode := w.shouldJSONEncodeSingleBareNode(nodes) + for i := range nodes { // clean resources by removing annotations set by the Reader if !w.KeepReaderAnnotations { @@ -81,10 +86,18 @@ func (w ByteWriter) Write(nodes []*yaml.RNode) error { } } + if jsonEncodeSingleBareNode { + encoder := json.NewEncoder(w.Writer) + encoder.SetIndent("", " ") + return errors.Wrap(encoder.Encode(nodes[0])) + } + + encoder := yaml.NewEncoder(w.Writer) + defer encoder.Close() // don't wrap the elements if w.WrappingKind == "" { for i := range nodes { - if err := w.encode(encoder, nodes[i].Document()); err != nil { + if err := encoder.Encode(nodes[i].Document()); err != nil { return err } } @@ -118,23 +131,37 @@ func (w ByteWriter) Write(nodes []*yaml.RNode) error { for i := range nodes { items.Content = append(items.Content, nodes[i].YNode()) } - err := w.encode(encoder, doc) - yaml.UndoSerializationHacksOnNodes(nodes) - return err -} - -// encode encodes the input document node to appropriate node format -func (w ByteWriter) encode(encoder *yaml.Encoder, doc *yaml.Node) error { - rNode := &yaml.RNode{} - rNode.SetYNode(doc) - str, err := rNode.String() - if err != nil { - return errors.Wrap(err) - } - if json.Valid([]byte(str)) { - je := json.NewEncoder(w.Writer) - je.SetIndent("", " ") - return errors.Wrap(je.Encode(rNode)) - } return encoder.Encode(doc) } + +func copyRNodes(in []*yaml.RNode) []*yaml.RNode { + out := make([]*yaml.RNode, len(in)) + for i := range in { + out[i] = in[i].Copy() + } + return out +} + +// shouldJSONEncodeSingleBareNode determines if nodes contain a single node that should not be +// wrapped and has a JSON file extension, which in turn means that the node should be JSON encoded. +// Note 1: this must be checked before any annotations to avoid losing information about the target +// filename extension. +// Note 2: JSON encoding should only be used for single, unwrapped nodes because multiple unwrapped +// nodes cannot be represented in JSON (no multi doc support). Furthermore, the typical use +// cases for wrapping nodes would likely not include later writing the whole wrapper to a +// .json file, i.e. there is no point risking any edge case information loss e.g. comments +// disappearing, that could come from JSON encoding the whole wrapper just to ensure that +// one (or all nodes) can be read as JSON. +func (w ByteWriter) shouldJSONEncodeSingleBareNode(nodes []*yaml.RNode) bool { + if w.WrappingKind == "" && len(nodes) == 1 { + if path, _, _ := kioutil.GetFileAnnotations(nodes[0]); path != "" { + filename := filepath.Base(path) + for _, glob := range JSONMatch { + if match, _ := filepath.Match(glob, filename); match { + return true + } + } + } + } + return false +} diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/kio/filters/merge3.go b/vendor/sigs.k8s.io/kustomize/kyaml/kio/filters/merge3.go index 27dd0f766..26ff86301 100644 --- a/vendor/sigs.k8s.io/kustomize/kyaml/kio/filters/merge3.go +++ b/vendor/sigs.k8s.io/kustomize/kyaml/kio/filters/merge3.go @@ -19,17 +19,55 @@ const ( mergeSourceDest = "dest" ) +// ResourceMatcher interface is used to match two resources based on IsSameResource implementation +// This is the way to group same logical resources in upstream, local and origin for merge +// The default way to group them is using GVKNN similar to how kubernetes server identifies resources +// Users of this library might have their own interpretation of grouping similar resources +// for e.g. if consumer adds a name-prefix to local resource, it should not be treated as new resource +// for updates etc. +// Hence, the callers of this library may pass different implementation for IsSameResource +type ResourceMatcher interface { + IsSameResource(node1, node2 *yaml.RNode) bool +} + +// ResourceMergeStrategy is the return type from the Handle function in the +// ResourceHandler interface. It determines which version of a resource should +// be included in the output (if any). +type ResourceMergeStrategy int + +const ( + // Merge means the output to dest should be the 3-way merge of original, + // updated and dest. + Merge ResourceMergeStrategy = iota + // KeepDest means the version of the resource in dest should be the output. + KeepDest + // KeepUpdated means the version of the resource in updated should be the + // output. + KeepUpdated + // KeepOriginal means the version of the resource in original should be the + // output. + KeepOriginal + // Skip means the resource should not be included in the output. + Skip +) + +// ResourceHandler interface is used to determine what should be done for a +// resource once the versions in original, updated and dest has been +// identified based on the ResourceMatcher. This allows users to customize +// what should be the result in dest if a resource has been deleted from +// upstream. +type ResourceHandler interface { + Handle(original, updated, dest *yaml.RNode) (ResourceMergeStrategy, error) +} + // Merge3 performs a 3-way merge on the original, updated, and destination packages. type Merge3 struct { OriginalPath string UpdatedPath string DestPath string MatchFilesGlob []string - - // MergeOnPath will use the relative filepath as part of the merge key. - // This may be necessary if the directory contains multiple copies of - // the same resource, or resources patches. - MergeOnPath bool + Matcher ResourceMatcher + Handler ResourceHandler } func (m Merge3) Merge() error { @@ -67,7 +105,16 @@ func (m Merge3) Merge() error { // Filter combines Resources with the same GVK + N + NS into tuples, and then merges them func (m Merge3) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) { // index the nodes by their identity - tl := tuples{mergeOnPath: m.MergeOnPath} + matcher := m.Matcher + if matcher == nil { + matcher = &DefaultGVKNNMatcher{MergeOnPath: true} + } + handler := m.Handler + if handler == nil { + handler = &DefaultResourceHandler{} + } + + tl := tuples{matcher: matcher} for i := range nodes { if err := tl.add(nodes[i]); err != nil { return nil, err @@ -78,21 +125,12 @@ func (m Merge3) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) { var output []*yaml.RNode for i := range tl.list { t := tl.list[i] - switch { - case t.original == nil && t.updated == nil && t.dest != nil: - // added locally -- keep dest - output = append(output, t.dest) - case t.original == nil && t.updated != nil && t.dest == nil: - // added in the update -- add update - output = append(output, t.updated) - case t.original != nil && t.updated == nil: - // deleted in the update - // don't include the resource in the output - case t.original != nil && t.dest == nil: - // deleted locally - // don't include the resource in the output - default: - // dest and updated are non-nil -- merge them + strategy, err := handler.Handle(t.original, t.updated, t.dest) + if err != nil { + return nil, err + } + switch strategy { + case Merge: node, err := t.merge() if err != nil { return nil, err @@ -100,6 +138,14 @@ func (m Merge3) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) { if node != nil { output = append(output, node) } + case KeepDest: + output = append(output, t.dest) + case KeepUpdated: + output = append(output, t.updated) + case KeepOriginal: + output = append(output, t.original) + case Skip: + // do nothing } } return output, nil @@ -109,13 +155,35 @@ func (m Merge3) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) { type tuples struct { list []*tuple - // mergeOnPath if set to true will use the resource filepath - // as part of the merge key - mergeOnPath bool + // matcher matches the resources for merge + matcher ResourceMatcher } -// isSameResource returns true if meta1 and meta2 are for the same logic resource -func (ts *tuples) isSameResource(meta1, meta2 yaml.ResourceMeta) bool { +// DefaultGVKNNMatcher holds the default matching of resources implementation based on +// Group, Version, Kind, Name and Namespace of the resource +type DefaultGVKNNMatcher struct { + // MergeOnPath will use the relative filepath as part of the merge key. + // This may be necessary if the directory contains multiple copies of + // the same resource, or resources patches. + MergeOnPath bool +} + +// IsSameResource returns true if metadata of node1 and metadata of node2 belongs to same logical resource +func (dm *DefaultGVKNNMatcher) IsSameResource(node1, node2 *yaml.RNode) bool { + if node1 == nil || node2 == nil { + return false + } + + meta1, err := node1.GetMeta() + if err != nil { + return false + } + + meta2, err := node2.GetMeta() + if err != nil { + return false + } + if meta1.Name != meta2.Name { return false } @@ -128,7 +196,7 @@ func (ts *tuples) isSameResource(meta1, meta2 yaml.ResourceMeta) bool { if meta1.Kind != meta2.Kind { return false } - if ts.mergeOnPath { + if dm.MergeOnPath { // directories may contain multiple copies of a resource with the same // name, namespace, apiVersion and kind -- e.g. kustomize patches, or // multiple environments @@ -143,17 +211,13 @@ func (ts *tuples) isSameResource(meta1, meta2 yaml.ResourceMeta) bool { // add adds a node to the list, combining it with an existing matching Resource if found func (ts *tuples) add(node *yaml.RNode) error { - nodeMeta, err := node.GetMeta() - if err != nil { - return err - } for i := range ts.list { t := ts.list[i] - if ts.isSameResource(t.meta, nodeMeta) { + if ts.matcher.IsSameResource(addedNode(t), node) { return t.add(node) } } - t := &tuple{meta: nodeMeta} + t := &tuple{} if err := t.add(node); err != nil { return err } @@ -161,9 +225,19 @@ func (ts *tuples) add(node *yaml.RNode) error { return nil } +// addedNode returns one on the existing added nodes in the tuple +func addedNode(t *tuple) *yaml.RNode { + if t.updated != nil { + return t.updated + } + if t.original != nil { + return t.original + } + return t.dest +} + // tuple wraps an original, updated, and dest tuple for a given Resource type tuple struct { - meta yaml.ResourceMeta original *yaml.RNode updated *yaml.RNode dest *yaml.RNode @@ -178,17 +252,17 @@ func (t *tuple) add(node *yaml.RNode) error { switch meta.Annotations[mergeSourceAnnotation] { case mergeSourceDest: if t.dest != nil { - return fmt.Errorf("dest source already specified") + return duplicateError("local", meta.Annotations[kioutil.PathAnnotation]) } t.dest = node case mergeSourceOriginal: if t.original != nil { - return fmt.Errorf("original source already specified") + return duplicateError("original upstream", meta.Annotations[kioutil.PathAnnotation]) } t.original = node case mergeSourceUpdated: if t.updated != nil { - return fmt.Errorf("updated source already specified") + return duplicateError("updated upstream", meta.Annotations[kioutil.PathAnnotation]) } t.updated = node default: @@ -201,3 +275,37 @@ func (t *tuple) add(node *yaml.RNode) error { func (t *tuple) merge() (*yaml.RNode, error) { return merge3.Merge(t.dest, t.original, t.updated) } + +// duplicateError returns duplicate resources error +func duplicateError(source, filePath string) error { + return fmt.Errorf(`found duplicate %q resources in file %q, please refer to "update" documentation for the fix`, source, filePath) +} + +// DefaultResourceHandler is the default implementation of the ResourceHandler +// interface. It uses the following rules: +// * Keep dest if resource only exists in dest. +// * Keep updated if resource added in updated. +// * Delete dest if updated has been deleted. +// * Don't add the resource back if removed from dest. +// * Otherwise merge. +type DefaultResourceHandler struct{} + +func (*DefaultResourceHandler) Handle(original, updated, dest *yaml.RNode) (ResourceMergeStrategy, error) { + switch { + case original == nil && updated == nil && dest != nil: + // added locally -- keep dest + return KeepDest, nil + case updated != nil && dest == nil: + // added in the update -- add update + return KeepUpdated, nil + case original != nil && updated == nil: + // deleted in the update + return Skip, nil + case original != nil && dest == nil: + // deleted locally + return Skip, nil + default: + // dest and updated are non-nil -- merge them + return Merge, nil + } +} diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/kio/ignorefilesmatcher.go b/vendor/sigs.k8s.io/kustomize/kyaml/kio/ignorefilesmatcher.go index 9a6ce924b..0ba3d8382 100644 --- a/vendor/sigs.k8s.io/kustomize/kyaml/kio/ignorefilesmatcher.go +++ b/vendor/sigs.k8s.io/kustomize/kyaml/kio/ignorefilesmatcher.go @@ -4,12 +4,14 @@ package kio import ( + "errors" "os" "path/filepath" "strings" - "github.com/monochromegane/go-gitignore" + gitignore "github.com/monochromegane/go-gitignore" "sigs.k8s.io/kustomize/kyaml/ext" + "sigs.k8s.io/kustomize/kyaml/filesys" ) // ignoreFilesMatcher handles `.krmignore` files, which allows for ignoring @@ -32,6 +34,7 @@ import ( // is set to true type ignoreFilesMatcher struct { matchers []matcher + fs filesys.FileSystemOrOnDisk } // readIgnoreFile checks whether there is a .krmignore file in the path, and @@ -39,9 +42,9 @@ type ignoreFilesMatcher struct { // we just add a matcher that match nothing. func (i *ignoreFilesMatcher) readIgnoreFile(path string) error { i.verifyPath(path) - m, err := gitignore.NewGitIgnore(filepath.Join(path, ext.IgnoreFileName())) + f, err := i.fs.Open(filepath.Join(path, ext.IgnoreFileName())) if err != nil { - if os.IsNotExist(err) { + if errors.Is(err, os.ErrNotExist) { i.matchers = append(i.matchers, matcher{ matcher: gitignore.DummyIgnoreMatcher(false), basePath: path, @@ -50,8 +53,10 @@ func (i *ignoreFilesMatcher) readIgnoreFile(path string) error { } return err } + defer f.Close() + i.matchers = append(i.matchers, matcher{ - matcher: m, + matcher: gitignore.NewGitIgnoreFromReader(path, f), basePath: path, }) return nil diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/openapi/openapi.go b/vendor/sigs.k8s.io/kustomize/kyaml/openapi/openapi.go index 5b7857606..5e34195f6 100644 --- a/vendor/sigs.k8s.io/kustomize/kyaml/openapi/openapi.go +++ b/vendor/sigs.k8s.io/kustomize/kyaml/openapi/openapi.go @@ -11,7 +11,7 @@ import ( "reflect" "strings" - "github.com/go-openapi/spec" + "k8s.io/kube-openapi/pkg/validation/spec" "sigs.k8s.io/kustomize/kyaml/errors" "sigs.k8s.io/kustomize/kyaml/openapi/kubernetesapi" "sigs.k8s.io/kustomize/kyaml/openapi/kustomizationapi" @@ -273,6 +273,15 @@ func IsNamespaceScoped(typeMeta yaml.TypeMeta) (bool, bool) { return isNamespaceScoped, found } +// IsCertainlyClusterScoped returns true for Node, Namespace, etc. and +// false for Pod, Deployment, etc. and kinds that aren't recognized in the +// openapi data. See: +// https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces +func IsCertainlyClusterScoped(typeMeta yaml.TypeMeta) bool { + nsScoped, found := IsNamespaceScoped(typeMeta) + return found && !nsScoped +} + // SuppressBuiltInSchemaUse can be called to prevent using the built-in Kubernetes // schema as part of the global schema. // Must be called before the schema is used. diff --git a/vendor/sigs.k8s.io/kustomize/api/resid/gvk.go b/vendor/sigs.k8s.io/kustomize/kyaml/resid/gvk.go similarity index 82% rename from vendor/sigs.k8s.io/kustomize/api/resid/gvk.go rename to vendor/sigs.k8s.io/kustomize/kyaml/resid/gvk.go index b112151d3..21dad78d3 100644 --- a/vendor/sigs.k8s.io/kustomize/api/resid/gvk.go +++ b/vendor/sigs.k8s.io/kustomize/kyaml/resid/gvk.go @@ -16,13 +16,26 @@ type Gvk struct { Group string `json:"group,omitempty" yaml:"group,omitempty"` Version string `json:"version,omitempty" yaml:"version,omitempty"` Kind string `json:"kind,omitempty" yaml:"kind,omitempty"` + // isClusterScoped is true if the object is known, per the openapi + // data in use, to be cluster scoped, and false otherwise. + isClusterScoped bool +} + +func NewGvk(g, v, k string) Gvk { + result := Gvk{Group: g, Version: v, Kind: k} + result.isClusterScoped = + openapi.IsCertainlyClusterScoped(result.AsTypeMeta()) + return result +} + +func GvkFromNode(r *yaml.RNode) Gvk { + g, v := ParseGroupVersion(r.GetApiVersion()) + return NewGvk(g, v, r.GetKind()) } // FromKind makes a Gvk with only the kind specified. func FromKind(k string) Gvk { - return Gvk{ - Kind: k, - } + return NewGvk("", "", k) } // ParseGroupVersion parses a KRM metadata apiVersion field. @@ -56,11 +69,7 @@ func GvkFromString(s string) Gvk { if k == noKind { k = "" } - return Gvk{ - Group: g, - Version: v, - Kind: k, - } + return NewGvk(g, v, k) } // Values that are brief but meaningful in logs. @@ -90,10 +99,13 @@ func (x Gvk) String() string { // ApiVersion returns the combination of Group and Version func (x Gvk) ApiVersion() string { - if x.Group == "" { - return x.Version + var sb strings.Builder + if x.Group != "" { + sb.WriteString(x.Group) + sb.WriteString("/") } - return x.Group + "/" + x.Version + sb.WriteString(x.Version) + return sb.String() } // StringWoEmptyField returns a string representation of the GVK. Non-exist @@ -207,26 +219,16 @@ func (x Gvk) IsSelected(selector *Gvk) bool { return true } -// toKyamlTypeMeta returns a yaml.TypeMeta from x's information. -func (x Gvk) toKyamlTypeMeta() yaml.TypeMeta { - var apiVersion strings.Builder - if x.Group != "" { - apiVersion.WriteString(x.Group) - apiVersion.WriteString("/") - } - apiVersion.WriteString(x.Version) +// AsTypeMeta returns a yaml.TypeMeta from x's information. +func (x Gvk) AsTypeMeta() yaml.TypeMeta { return yaml.TypeMeta{ - APIVersion: apiVersion.String(), + APIVersion: x.ApiVersion(), Kind: x.Kind, } } -// IsNamespaceableKind returns true if x is a namespaceable Gvk, -// e.g. instances of Pod and Deployment are namespaceable, -// but instances of Node and Namespace are not namespaceable. -// Alternative name for this method: IsNotClusterScoped. -// Implements https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/#not-all-objects-are-in-a-namespace -func (x Gvk) IsNamespaceableKind() bool { - isNamespaceScoped, found := openapi.IsNamespaceScoped(x.toKyamlTypeMeta()) - return !found || isNamespaceScoped +// IsClusterScoped returns true if the Gvk is certainly cluster scoped +// with respect to the available openapi data. +func (x Gvk) IsClusterScoped() bool { + return x.isClusterScoped } diff --git a/vendor/sigs.k8s.io/kustomize/api/resid/resid.go b/vendor/sigs.k8s.io/kustomize/kyaml/resid/resid.go similarity index 83% rename from vendor/sigs.k8s.io/kustomize/api/resid/resid.go rename to vendor/sigs.k8s.io/kustomize/kyaml/resid/resid.go index 28310e8f3..1700531a2 100644 --- a/vendor/sigs.k8s.io/kustomize/api/resid/resid.go +++ b/vendor/sigs.k8s.io/kustomize/kyaml/resid/resid.go @@ -12,13 +12,10 @@ type ResId struct { // Gvk of the resource. Gvk `json:",inline,omitempty" yaml:",inline,omitempty"` - // Name of the resource before transformation. + // Name of the resource. Name string `json:"name,omitempty" yaml:"name,omitempty"` - // Namespace the resource belongs to. - // An untransformed resource has no namespace. - // A fully transformed resource has the namespace - // from the top most overlay. + // Namespace the resource belongs to, if it can belong to a namespace. Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` } @@ -30,12 +27,12 @@ func NewResIdWithNamespace(k Gvk, n, ns string) ResId { // NewResId creates new ResId. func NewResId(k Gvk, n string) ResId { - return ResId{Gvk: k, Name: n} + return NewResIdWithNamespace(k, n, "") } // NewResIdKindOnly creates a new ResId. func NewResIdKindOnly(k string, n string) ResId { - return ResId{Gvk: FromKind(k), Name: n} + return NewResId(FromKind(k), n) } const ( @@ -90,6 +87,13 @@ func (id ResId) GvknEquals(o ResId) bool { return id.Name == o.Name && id.Gvk.Equals(o.Gvk) } +// IsSelectedBy returns true if self is selected by the argument. +func (id ResId) IsSelectedBy(selector ResId) bool { + return (selector.Name == "" || selector.Name == id.Name) && + (selector.Namespace == "" || selector.IsNsEquals(id)) && + id.Gvk.IsSelected(&selector.Gvk) +} + // Equals returns true if the other id matches // namespace/Group/Version/Kind/name. func (id ResId) Equals(o ResId) bool { @@ -106,7 +110,7 @@ func (id ResId) IsNsEquals(o ResId) bool { // ResId and the Namespace is either not set or set // to DefaultNamespace. func (id ResId) IsInDefaultNs() bool { - return id.IsNamespaceableKind() && id.isPutativelyDefaultNs() + return !id.IsClusterScoped() && id.isPutativelyDefaultNs() } func (id ResId) isPutativelyDefaultNs() bool { @@ -117,7 +121,7 @@ func (id ResId) isPutativelyDefaultNs() bool { // namespace for use in reporting and equality tests. func (id ResId) EffectiveNamespace() string { // The order of these checks matters. - if !id.IsNamespaceableKind() { + if id.IsClusterScoped() { return TotallyNotANamespace } if id.isPutativelyDefaultNs() { diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/runfn/runfn.go b/vendor/sigs.k8s.io/kustomize/kyaml/runfn/runfn.go index 5f5481797..bfe1ac3f2 100644 --- a/vendor/sigs.k8s.io/kustomize/kyaml/runfn/runfn.go +++ b/vendor/sigs.k8s.io/kustomize/kyaml/runfn/runfn.go @@ -496,7 +496,6 @@ func (r *RunFns) ffp(spec runtimeutil.FunctionSpec, api *yaml.RNode, currentUser } p = filepath.ToSlash(filepath.Join(r.Path, filepath.Dir(p), spec.Starlark.Path)) } - fmt.Println(p) sf := &starlark.Filter{Name: spec.Starlark.Name, Path: p, URL: spec.Starlark.URL} diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/yaml/alias.go b/vendor/sigs.k8s.io/kustomize/kyaml/yaml/alias.go index ee0d5cbb1..05cafae0d 100644 --- a/vendor/sigs.k8s.io/kustomize/kyaml/yaml/alias.go +++ b/vendor/sigs.k8s.io/kustomize/kyaml/yaml/alias.go @@ -4,11 +4,21 @@ package yaml import ( + "bytes" "io" - "gopkg.in/yaml.v3" + "sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml" ) +const CompactSequenceStyle = "compact" +const WideSequenceStyle = "wide" + +const DefaultIndent = 2 +const DefaultSequenceStyle = CompactSequenceStyle + +var sequenceIndentationStyle = DefaultSequenceStyle +var indent = DefaultIndent + // Expose the yaml.v3 functions so this package can be used as a replacement type Decoder = yaml.Decoder @@ -21,12 +31,22 @@ type Style = yaml.Style type TypeError = yaml.TypeError type Unmarshaler = yaml.Unmarshaler -var Marshal = yaml.Marshal +var Marshal = func(in interface{}) ([]byte, error) { + var buf bytes.Buffer + err := NewEncoder(&buf).Encode(in) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} var Unmarshal = yaml.Unmarshal var NewDecoder = yaml.NewDecoder var NewEncoder = func(w io.Writer) *yaml.Encoder { e := yaml.NewEncoder(w) - e.SetIndent(2) + e.SetIndent(indent) + if sequenceIndentationStyle == CompactSequenceStyle { + e.CompactSeqIndent() + } return e } diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/yaml/compatibility.go b/vendor/sigs.k8s.io/kustomize/kyaml/yaml/compatibility.go index e2cd811ce..a47114000 100644 --- a/vendor/sigs.k8s.io/kustomize/kyaml/yaml/compatibility.go +++ b/vendor/sigs.k8s.io/kustomize/kyaml/yaml/compatibility.go @@ -7,9 +7,9 @@ import ( "reflect" "strings" - "github.com/go-openapi/spec" y1_1 "gopkg.in/yaml.v2" - y1_2 "gopkg.in/yaml.v3" + "k8s.io/kube-openapi/pkg/validation/spec" + y1_2 "sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml" ) // typeToTag maps OpenAPI schema types to yaml 1.2 tags @@ -45,6 +45,14 @@ func FormatNonStringStyle(node *Node, schema spec.Schema) { default: return } + + // if the node tag is null, make sure we don't add any non-null tags + // https://github.com/GoogleContainerTools/kpt/issues/2321 + if node.Tag == NodeTagNull { + // must NOT quote null values + node.Style = 0 + return + } if tag, found := typeToTag[t]; found { // make sure the right tag is set node.Tag = tag diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/yaml/fns.go b/vendor/sigs.k8s.io/kustomize/kyaml/yaml/fns.go index ab01b9815..5289997dd 100644 --- a/vendor/sigs.k8s.io/kustomize/kyaml/yaml/fns.go +++ b/vendor/sigs.k8s.io/kustomize/kyaml/yaml/fns.go @@ -10,8 +10,8 @@ import ( "strings" "github.com/davecgh/go-spew/spew" - "gopkg.in/yaml.v3" "sigs.k8s.io/kustomize/kyaml/errors" + "sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml" ) // Append creates an ElementAppender diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/yaml/internal/k8sgen/pkg/labels/selector.go b/vendor/sigs.k8s.io/kustomize/kyaml/yaml/internal/k8sgen/pkg/labels/selector.go index 73c5ae6a6..2999eddd5 100644 --- a/vendor/sigs.k8s.io/kustomize/kyaml/yaml/internal/k8sgen/pkg/labels/selector.go +++ b/vendor/sigs.k8s.io/kustomize/kyaml/yaml/internal/k8sgen/pkg/labels/selector.go @@ -27,6 +27,7 @@ import ( "strings" "log" + "sigs.k8s.io/kustomize/kyaml/yaml/internal/k8sgen/pkg/selection" "sigs.k8s.io/kustomize/kyaml/yaml/internal/k8sgen/pkg/util/sets" "sigs.k8s.io/kustomize/kyaml/yaml/internal/k8sgen/pkg/util/validation" diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/yaml/kfns.go b/vendor/sigs.k8s.io/kustomize/kyaml/yaml/kfns.go index d9e5dfaf6..2ae8c1665 100644 --- a/vendor/sigs.k8s.io/kustomize/kyaml/yaml/kfns.go +++ b/vendor/sigs.k8s.io/kustomize/kyaml/yaml/kfns.go @@ -4,8 +4,8 @@ package yaml import ( - "gopkg.in/yaml.v3" "sigs.k8s.io/kustomize/kyaml/errors" + "sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml" ) // AnnotationClearer removes an annotation at metadata.annotations. diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/yaml/rnode.go b/vendor/sigs.k8s.io/kustomize/kyaml/yaml/rnode.go index 9b1b5ff1b..f7e3f230c 100644 --- a/vendor/sigs.k8s.io/kustomize/kyaml/yaml/rnode.go +++ b/vendor/sigs.k8s.io/kustomize/kyaml/yaml/rnode.go @@ -12,8 +12,8 @@ import ( "strconv" "strings" - "gopkg.in/yaml.v3" "sigs.k8s.io/kustomize/kyaml/errors" + "sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml" "sigs.k8s.io/kustomize/kyaml/yaml/internal/k8sgen/pkg/labels" ) @@ -337,26 +337,83 @@ func (rn *RNode) SetYNode(node *yaml.Node) { *rn.value = *node } -// GetKind returns the kind. +// GetKind returns the kind, if it exists, else empty string. func (rn *RNode) GetKind() string { - node, err := rn.Pipe(FieldMatcher{Name: KindField}) - if err != nil { - return "" + if node := rn.getMapFieldValue(KindField); node != nil { + return node.Value } - return GetValue(node) + return "" } -// GetName returns the name. +// SetKind sets the kind. +func (rn *RNode) SetKind(k string) { + rn.SetMapField(NewScalarRNode(k), KindField) +} + +// GetApiVersion returns the apiversion, if it exists, else empty string. +func (rn *RNode) GetApiVersion() string { + if node := rn.getMapFieldValue(APIVersionField); node != nil { + return node.Value + } + return "" +} + +// SetApiVersion sets the apiVersion. +func (rn *RNode) SetApiVersion(av string) { + rn.SetMapField(NewScalarRNode(av), APIVersionField) +} + +// getMapFieldValue returns the value (*yaml.Node) of a mapping field. +// The value might be nil. Also, the function returns nil, not an error, +// if this node is not a mapping node, or if this node does not have the +// given field, so this function cannot be used to make distinctions +// between these cases. +func (rn *RNode) getMapFieldValue(field string) *yaml.Node { + for i := 0; i < len(rn.Content()); i = IncrementFieldIndex(i) { + if rn.Content()[i].Value == field { + return rn.Content()[i+1] + } + } + return nil +} + +// GetName returns the name, or empty string if +// field not found. The setter is more restrictive. func (rn *RNode) GetName() string { - f := rn.Field(MetadataField) + return rn.getMetaStringField(NameField) +} + +// getMetaStringField returns the value of a string field in metadata. +func (rn *RNode) getMetaStringField(fName string) string { + md := rn.getMetaData() + if md == nil { + return "" + } + f := md.Field(fName) if f.IsNilOrEmpty() { return "" } - f = f.Value.Field(NameField) - if f.IsNilOrEmpty() { - return "" + return GetValue(f.Value) +} + +// getMetaData returns the RNode holding the value of the metadata field. +// Return nil if field not found (no error). +func (rn *RNode) getMetaData() *RNode { + if IsMissingOrNull(rn) { + return nil } - return f.Value.YNode().Value + var n *RNode + if rn.YNode().Kind == DocumentNode { + // get the content if this is the document node + n = NewRNode(rn.Content()[0]) + } else { + n = rn + } + mf := n.Field(MetadataField) + if mf.IsNilOrEmpty() { + return nil + } + return mf.Value } // SetName sets the metadata name field. @@ -364,16 +421,14 @@ func (rn *RNode) SetName(name string) error { return rn.SetMapField(NewScalarRNode(name), MetadataField, NameField) } -// GetNamespace gets the metadata namespace field. -func (rn *RNode) GetNamespace() (string, error) { - meta, err := rn.GetMeta() - if err != nil { - return "", err - } - return meta.Namespace, nil +// GetNamespace gets the metadata namespace field, or empty string if +// field not found. The setter is more restrictive. +func (rn *RNode) GetNamespace() string { + return rn.getMetaStringField(NamespaceField) } -// SetNamespace tries to set the metadata namespace field. +// SetNamespace tries to set the metadata namespace field. If the argument +// is empty, the field is dropped. func (rn *RNode) SetNamespace(ns string) error { meta, err := rn.Pipe(Lookup(MetadataField)) if err != nil { @@ -390,12 +445,14 @@ func (rn *RNode) SetNamespace(ns string) error { } // GetAnnotations gets the metadata annotations field. -func (rn *RNode) GetAnnotations() (map[string]string, error) { - meta, err := rn.GetMeta() - if err != nil { - return nil, err +// If the field is missing, returns an empty map. +// Use another method to check for missing metadata. +func (rn *RNode) GetAnnotations() map[string]string { + meta := rn.getMetaData() + if meta == nil { + return make(map[string]string) } - return meta.Annotations, nil + return rn.getMapFromMeta(meta, AnnotationsField) } // SetAnnotations tries to set the metadata annotations field. @@ -404,12 +461,26 @@ func (rn *RNode) SetAnnotations(m map[string]string) error { } // GetLabels gets the metadata labels field. -func (rn *RNode) GetLabels() (map[string]string, error) { - meta, err := rn.GetMeta() - if err != nil { - return nil, err +// If the field is missing, returns an empty map. +// Use another method to check for missing metadata. +func (rn *RNode) GetLabels() map[string]string { + meta := rn.getMetaData() + if meta == nil { + return make(map[string]string) } - return meta.Labels, nil + return rn.getMapFromMeta(meta, LabelsField) +} + +// getMapFromMeta returns map, sometimes empty, from metadata. +func (rn *RNode) getMapFromMeta(meta *RNode, fName string) map[string]string { + result := make(map[string]string) + if f := meta.Field(fName); !f.IsNilOrEmpty() { + _ = f.Value.VisitFields(func(node *MapNode) error { + result[GetValue(node.Key)] = GetValue(node.Value) + return nil + }) + } + return result } // SetLabels sets the metadata labels field. @@ -419,7 +490,7 @@ func (rn *RNode) SetLabels(m map[string]string) error { // This established proper quoting on string values, and sorts by key. func (rn *RNode) setMapInMetadata(m map[string]string, field string) error { - meta, err := rn.Pipe(Lookup(MetadataField)) + meta, err := rn.Pipe(LookupCreate(MappingNode, MetadataField)) if err != nil { return err } @@ -475,6 +546,32 @@ func (rn *RNode) GetBinaryDataMap() map[string]string { return result } +// GetValidatedDataMap retrieves the data map and returns an error if the data +// map contains entries which are not included in the expectedKeys set. +func (rn *RNode) GetValidatedDataMap(expectedKeys []string) (map[string]string, error) { + dataMap := rn.GetDataMap() + err := rn.validateDataMap(dataMap, expectedKeys) + return dataMap, err +} + +func (rn *RNode) validateDataMap(dataMap map[string]string, expectedKeys []string) error { + if dataMap == nil { + return fmt.Errorf("The datamap is unassigned") + } + for key := range dataMap { + found := false + for _, expected := range expectedKeys { + if expected == key { + found = true + } + } + if !found { + return fmt.Errorf("an unexpected key (%v) was found", key) + } + } + return nil +} + func (rn *RNode) SetDataMap(m map[string]string) { if rn == nil { log.Fatal("cannot set data map on nil Rnode") @@ -786,11 +883,7 @@ func (rn *RNode) MatchesAnnotationSelector(selector string) (bool, error) { if err != nil { return false, err } - slice, err := rn.GetAnnotations() - if err != nil { - return false, err - } - return s.Matches(labels.Set(slice)), nil + return s.Matches(labels.Set(rn.GetAnnotations())), nil } // MatchesLabelSelector returns true on a selector match to labels. @@ -799,11 +892,7 @@ func (rn *RNode) MatchesLabelSelector(selector string) (bool, error) { if err != nil { return false, err } - slice, err := rn.GetLabels() - if err != nil { - return false, err - } - return s.Matches(labels.Set(slice)), nil + return s.Matches(labels.Set(rn.GetLabels())), nil } // HasNilEntryInList returns true if the RNode contains a list which has diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/yaml/serialization.go b/vendor/sigs.k8s.io/kustomize/kyaml/yaml/serialization.go deleted file mode 100644 index 92510c518..000000000 --- a/vendor/sigs.k8s.io/kustomize/kyaml/yaml/serialization.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2019 The Kubernetes Authors. -// SPDX-License-Identifier: Apache-2.0 - -package yaml - -import "gopkg.in/yaml.v3" - -func DoSerializationHacksOnNodes(nodes []*RNode) { - for _, node := range nodes { - DoSerializationHacks(node.YNode()) - } -} - -// DoSerializationHacks addresses a bug in yaml V3 upstream, it parses the yaml node, -// and rearranges the head comments of the children of sequence node. -// Refer to https://github.com/go-yaml/yaml/issues/587 for more details -func DoSerializationHacks(node *yaml.Node) { - switch node.Kind { - case DocumentNode: - for _, node := range node.Content { - DoSerializationHacks(node) - } - - case MappingNode: - for _, node := range node.Content { - DoSerializationHacks(node) - } - - case SequenceNode: - for _, node := range node.Content { - // for each child mapping node, transfer the head comment of it's - // first child scalar node to the head comment of itself - // This is necessary to address serialization issue - // https://github.com/go-yaml/yaml/issues/587 in go-yaml.v3 - // Remove this hack when the issue has been resolved - if len(node.Content) > 0 && node.Content[0].Kind == ScalarNode { - node.HeadComment = node.Content[0].HeadComment - node.Content[0].HeadComment = "" - } - } - } -} - -func UndoSerializationHacksOnNodes(nodes []*RNode) { - for _, node := range nodes { - UndoSerializationHacks(node.YNode()) - } -} - -// UndoSerializationHacks reverts the changes made by DoSerializationHacks -// Refer to https://github.com/go-yaml/yaml/issues/587 for more details -func UndoSerializationHacks(node *yaml.Node) { - switch node.Kind { - case DocumentNode: - for _, node := range node.Content { - DoSerializationHacks(node) - } - - case MappingNode: - for _, node := range node.Content { - DoSerializationHacks(node) - } - - case SequenceNode: - for _, node := range node.Content { - // revert the changes made in DoSerializationHacks - // This is necessary to address serialization issue - // https://github.com/go-yaml/yaml/issues/587 in go-yaml.v3 - // Remove this hack when the issue has been resolved - if len(node.Content) > 0 && node.Content[0].Kind == ScalarNode { - node.Content[0].HeadComment = node.HeadComment - node.HeadComment = "" - } - } - } -} diff --git a/vendor/sigs.k8s.io/kustomize/kyaml/yaml/types.go b/vendor/sigs.k8s.io/kustomize/kyaml/yaml/types.go index 2c424e508..c4e06a578 100644 --- a/vendor/sigs.k8s.io/kustomize/kyaml/yaml/types.go +++ b/vendor/sigs.k8s.io/kustomize/kyaml/yaml/types.go @@ -7,8 +7,8 @@ import ( "bytes" "strings" - "gopkg.in/yaml.v3" "sigs.k8s.io/kustomize/kyaml/errors" + "sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml" "sigs.k8s.io/kustomize/kyaml/sets" ) @@ -213,7 +213,10 @@ func String(node *yaml.Node, opts ...string) (string, error) { b := &bytes.Buffer{} e := NewEncoder(b) err := e.Encode(node) - e.Close() + errClose := e.Close() + if err == nil { + err = errClose + } val := b.String() if optsSet.Has(Trim) { val = strings.TrimSpace(val)