1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-05 15:37:19 +00:00

Implement global anchor (#2311)

* implement global anchor for patch strategic merge

Signed-off-by: Max Goncharenko <kacejot@fex.net>

* fixed unit tests for mutation global anchor

Signed-off-by: Max Goncharenko <kacejot@fex.net>

* added global anchor in validation

Signed-off-by: Max Goncharenko <kacejot@fex.net>

* fix some global anchor issues found during testing

Signed-off-by: Max Goncharenko <kacejot@fex.net>

* run go tidy

Signed-off-by: Maxim Goncharenko <goncharenko.maxim@apriorit.com>

* fixed tests

Signed-off-by: Maxim Goncharenko <goncharenko.maxim@apriorit.com>

* fixed some tests

Signed-off-by: Maxim Goncharenko <goncharenko.maxim@apriorit.com>

* finish implementing global anchor

Signed-off-by: Maxim Goncharenko <goncharenko.maxim@apriorit.com>

* WIP: lower global anchor strictness

Signed-off-by: Maxim Goncharenko <goncharenko.maxim@apriorit.com>

* Revert "WIP: lower global anchor strictness"

This reverts commit 08e176a042.

Signed-off-by: Maxim Goncharenko <goncharenko.maxim@apriorit.com>

* global anchor for mutation

Signed-off-by: Maxim Goncharenko <goncharenko.maxim@apriorit.com>
This commit is contained in:
Max Goncharenko 2021-09-13 18:59:28 +03:00 committed by GitHub
parent f6933bb439
commit a0ff8bbd0b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 551 additions and 222 deletions

8
go.mod
View file

@ -17,6 +17,7 @@ require (
github.com/google/go-containerregistry v0.6.0
github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20210216200643-d81088d9983e
github.com/googleapis/gnostic v0.5.4
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/jmespath/go-jmespath v0.4.0
github.com/julienschmidt/httprouter v1.3.0
github.com/kataras/tablewriter v0.0.0-20180708051242-e063d29b7c23
@ -24,6 +25,7 @@ require (
github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a
github.com/minio/minio v0.0.0-20200114012931-30922148fbb5
github.com/minio/pkg v1.0.7
github.com/nxadm/tail v1.4.8 // indirect
github.com/onsi/ginkgo v1.15.0
github.com/onsi/gomega v1.11.0
github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6
@ -31,10 +33,12 @@ require (
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.11.0
github.com/robfig/cron/v3 v3.0.1
github.com/sigstore/cosign v1.1.0
github.com/sigstore/sigstore v0.0.0-20210729211320-56a91f560f44
github.com/sigstore/cosign v1.0.0
github.com/sigstore/rekor v0.3.0 // indirect
github.com/sigstore/sigstore v0.0.0-20210726180807-7e34e36ecda1
github.com/spf13/cobra v1.2.1
github.com/stretchr/testify v1.7.0
github.com/xanzy/ssh-agent v0.3.0 // indirect
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
gotest.tools v2.2.0+incompatible

68
go.sum
View file

@ -28,9 +28,8 @@ cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
cloud.google.com/go v0.88.0 h1:MZ2cf9Elnv1wqccq8ooKO2MqHQLc+ChCp/+QWObCpxg=
cloud.google.com/go v0.88.0/go.mod h1:dnKwfYbP9hQhefiUvpbcAyoGSHUrOxR20JVElLiUvEY=
cloud.google.com/go v0.90.0 h1:MjvSkUq8RuAb+2JLDi5VQmmExRJPUQ3JLCWpRB6fmdw=
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
@ -55,7 +54,6 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.15.0/go.mod h1:mjjQMoxxyGH7Jr8K5qrx6N2O0AHsczI61sMNn03GIZI=
cloud.google.com/go/storage v1.16.0 h1:1UwAux2OZP4310YXg5ohqBEpV16Y93uZG4+qOX7K2Kg=
cloud.google.com/go/storage v1.16.0/go.mod h1:ieKBmUyzcftN5tbxwnXClMKH00CfcQ+xL6NN0r5QfmE=
code.gitea.io/sdk/gitea v0.11.3/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY=
contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA=
@ -79,6 +77,7 @@ github.com/Azure/azure-sdk-for-go v30.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9mo
github.com/Azure/azure-sdk-for-go v43.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v51.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v54.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v55.7.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v55.8.0+incompatible h1:EuccMPzxu67cIE95/mrtwQivLv7ETmURi5IUgLNVug8=
github.com/Azure/azure-sdk-for-go v55.8.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-service-bus-go v0.9.1/go.mod h1:yzBx6/BUGfjfeqbRZny9AQIbIe3AcV9WZbAdpkoXOa0=
@ -109,8 +108,9 @@ github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQW
github.com/Azure/go-autorest/autorest/adal v0.9.2/go.mod h1:/3SMAM86bP6wC9Ev35peQDUeqFZBMH07vvUOmg4z/fE=
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
github.com/Azure/go-autorest/autorest/adal v0.9.11/go.mod h1:nBKAnTomx8gDtl+3ZCJv2v0KACFHWTB2drffI1B68Pk=
github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q=
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/adal v0.9.14 h1:G8hexQdV5D4khOXrWG2YuLCFKhWYmWD8bHYaXN5ophk=
github.com/Azure/go-autorest/autorest/adal v0.9.14/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/azure/auth v0.5.7/go.mod h1:AkzUsqkrdmNhfP2i54HqINVQopw0CLDnvHpJ88Zz1eI=
github.com/Azure/go-autorest/autorest/azure/auth v0.5.8/go.mod h1:kxyKZTSfKh8OVFWPAgOgQ/frrJgeYQJPyR5fLFmXko4=
github.com/Azure/go-autorest/autorest/azure/cli v0.4.2/go.mod h1:7qkJkT+j6b+hIpzMOwPChJhTqS8VbsqqgULzMNRugoM=
@ -163,6 +163,7 @@ github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugX
github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
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 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU=
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
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=
@ -256,6 +257,7 @@ github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/
github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.39.6/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go v1.40.4/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go v1.40.7 h1:dD5+UZxedqHeE4WakJHEhTsEARYlq8kHkYEf89R1tEo=
github.com/aws/aws-sdk-go v1.40.7/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
@ -299,6 +301,7 @@ github.com/cavaliercoder/go-rpm v0.0.0-20200122174316-8cb9fd9c31a8/go.mod h1:AZI
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
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/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/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@ -454,9 +457,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyberphone/json-canonicalization v0.0.0-20210303052042-6bc126869bf4 h1:7AjYfmq7AmviXsuZjV5DcE7PuhJ4dWMi8gLllpLVDQY=
github.com/cyberphone/json-canonicalization v0.0.0-20210303052042-6bc126869bf4/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw=
github.com/cyberphone/json-canonicalization v0.0.0-20210823021906-dc406ceaf94b h1:lMzA7yYThpwx7iYNpTeiQnRH6h5JSfSYMJdz+pxZOW8=
github.com/cyberphone/json-canonicalization v0.0.0-20210823021906-dc406ceaf94b/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw=
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
@ -871,15 +873,14 @@ github.com/google/go-replayers/httpreplay v0.1.0/go.mod h1:YKZViNhiGgqdBlUbI2MwG
github.com/google/go-replayers/httpreplay v0.1.2/go.mod h1:YKZViNhiGgqdBlUbI2MwGpq4pXxNmhJLPHQ7cv2b5no=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/licenseclassifier v0.0.0-20210325184830-bb04aff29e72/go.mod h1:qsqn2hxC+vURpyBRygGUuinTO42MFRLcsmQ/P8v94+M=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible h1:xmapqc1AyLoB+ddYT6r04bD9lIjlOqGaREovi0SzFaE=
github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ=
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
@ -896,7 +897,6 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210715191844-86eeefc3e471/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0/go.mod h1:RaTPr0KUf2K7fnZYLNDrr8rxAamWs3iNywJLtQ2AzBg=
github.com/google/rpmpack v0.0.0-20210518075352-dc539ef4f2ea/go.mod h1:+y9lKiqDhR4zkLl+V9h4q0rdyrYVsWWm6LLCQP33DIk=
@ -949,8 +949,9 @@ github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
@ -1083,7 +1084,6 @@ github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
@ -1316,8 +1316,9 @@ github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso=
github.com/nsqio/go-nsq v1.0.7/go.mod h1:XP5zaUs3pqf+Q71EqUJs3HYfBIqfK6G83WQMdNN+Ito=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
@ -1352,7 +1353,7 @@ github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDs
github.com/onsi/gomega v1.11.0 h1:+CqWgvj0OZycCaqclBD1pxKHAU+tOkHmQIWvDHq2aug=
github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/open-policy-agent/opa v0.31.0/go.mod h1:aeLYiWaZe9ikcX67qLzmtRTOxj7psNYh6YGTbTW6V+s=
github.com/open-policy-agent/opa v0.30.2/go.mod h1:+Bv1G/E7Irxgm5zLNXiHuxYqMaqJUSKyBhIGxeneoGA=
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
@ -1462,6 +1463,7 @@ github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.29.0 h1:3jqPBvKT4OHAbje2Ql7KeaaSicDBCxMYwEJU1zRJceE=
@ -1532,14 +1534,16 @@ github.com/shibumi/go-pathspec v1.2.0/go.mod h1:bDxCftD0fST3qXIlHoQ/fChsU4mWMVkl
github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil/v3 v3.21.4/go.mod h1:ghfMypLDrFSWN2c9cDYFLHyynQ+QUht0cv/18ZqVczw=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sigstore/cosign v1.1.0 h1:fvoQAyR3N7GmRhE/Le02eo9qBWau0784wcIk7EjLJGQ=
github.com/sigstore/cosign v1.1.0/go.mod h1:L7DOTaKaaWG+EOB9IKk6g8CZqwawrmeMVukXFJPevzs=
github.com/sigstore/cosign v1.0.0 h1:jvsRP8ZfEc5jAnj2cGQo5S02VQ7h7rXwpiXYJF4n0+0=
github.com/sigstore/cosign v1.0.0/go.mod h1:XdYJiB4fkKo+OepAHtDgWU6n1MpP08eM8H2rIr5QU4U=
github.com/sigstore/fulcio v0.1.1/go.mod h1:HAsi0o0xMmBIauM9QkJ4dyvmeEzK1ZGcmH33gQ6xO3c=
github.com/sigstore/rekor v0.2.1-0.20210714185543-38d532d5c0b1/go.mod h1:cL9B3+/gp3BG+/bhkSHBA3MQZMten5xM6BhJYd5b5zU=
github.com/sigstore/rekor v0.3.0 h1:OBEvo/Rv8NKKtiWq0WRHgXFpVPe1fGiqz93dfBh/Myo=
github.com/sigstore/rekor v0.3.0/go.mod h1:cL9B3+/gp3BG+/bhkSHBA3MQZMten5xM6BhJYd5b5zU=
github.com/sigstore/sigstore v0.0.0-20210713222344-1fee53516622/go.mod h1:aOSeNrlcHsfUD8Q1hwWd8KloNqBnxEZlu4k47cFg5rg=
github.com/sigstore/sigstore v0.0.0-20210729211320-56a91f560f44 h1:V7tcgdv69z2dAn31YzOjc6tGuZHpjC3kcpYT+XJmw4s=
github.com/sigstore/sigstore v0.0.0-20210729211320-56a91f560f44/go.mod h1:rJpRn7XmR/YrfNGDU9jh+vy5WMeSv5YKfNDBwnFg+Qg=
github.com/sigstore/sigstore v0.0.0-20210722023421-fd3b69438dba/go.mod h1:p+VFprG1w+oRcb3fgEKa9uvw3/7N9TR0srIi2JerPKo=
github.com/sigstore/sigstore v0.0.0-20210726180807-7e34e36ecda1 h1:4pct+K5MTh3G4AbiSjYpYT3MVVI5WdDdJZEr9bTkLb8=
github.com/sigstore/sigstore v0.0.0-20210726180807-7e34e36ecda1/go.mod h1:/za/jqA/1XazvjIfvvtDkIAJZWKqkbcT5VTpHR7hnfQ=
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
@ -1627,16 +1631,13 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
github.com/tent/canonical-json-go v0.0.0-20130607151641-96e4ba3a7613 h1:iGnD/q9160NWqKZZ5vY4p0dMiYMRknzctfSkqA4nBDw=
github.com/tent/canonical-json-go v0.0.0-20130607151641-96e4ba3a7613/go.mod h1:g6AnIpDSYMcphz193otpSIzN+11Rs+AAIIC6rm1enug=
github.com/thales-e-security/pool v0.0.2/go.mod h1:qtpMm2+thHtqhLzTwgDBj/OuNnMpupY8mv0Phz0gjhU=
github.com/theupdateframework/go-tuf v0.0.0-20210630170422-22a94818d17b/go.mod h1:L+uU/NRFK/7h0NYAnsmvsX9EghDB5QVCcHCIrK2h5nw=
github.com/theupdateframework/go-tuf v0.0.0-20210722233521-90e262754396 h1:j4odVZMwglHp54CYsNHd0wls+lkQzxloQU9AQjQu0W4=
github.com/theupdateframework/go-tuf v0.0.0-20210722233521-90e262754396/go.mod h1:L+uU/NRFK/7h0NYAnsmvsX9EghDB5QVCcHCIrK2h5nw=
github.com/theupdateframework/go-tuf v0.0.0-20210804171843-477a5d73800a h1:jH3DSl+6QKbX+koCvBf3cP+1mLRANxk36/hUtvA6HVg=
github.com/theupdateframework/go-tuf v0.0.0-20210804171843-477a5d73800a/go.mod h1:aDPMGsrpdPQqJa0ryp7LovT6qSqZ/zKmUDTHZK+wIf4=
github.com/tidwall/gjson v1.3.5/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls=
github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
@ -1689,8 +1690,9 @@ github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59b
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
github.com/xanzy/go-gitlab v0.31.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug=
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
@ -1975,8 +1977,9 @@ golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210505214959-0714010a04ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210716203947-853a461950ff h1:j2EK/QoxYNBsXI4R7fQkkRUk8y6wnOBI+6hgPdP/6Ds=
golang.org/x/net v0.0.0-20210716203947-853a461950ff/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1996,9 +1999,8 @@ golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210615190721-d04028783cf1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914 h1:3B43BWw0xEBsLZ/NO1VALz6fppU3481pik+2Ksv45z8=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a h1:4Kd8OPUx1xgUwrHDaviWZO8MsgoZTZYC3g+8m16RBww=
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -2302,9 +2304,8 @@ google.golang.org/api v0.46.0/go.mod h1:ceL4oozhkAiTID8XMmJBsIxID/9wMXJVVFXPg4yl
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
google.golang.org/api v0.49.0/go.mod h1:BECiH72wsfwUvOVn3+btPD5WHi0LzavZReBndi42L18=
google.golang.org/api v0.50.0 h1:LX7NFCFYOHzr7WHaYiRUpeipZe9o5L8T+2F4Z798VDw=
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
google.golang.org/api v0.51.0 h1:SQaA2Cx57B+iPw2MBgyjEkoeMkRK2IenSGoia0U3lCk=
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
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=
@ -2388,12 +2389,10 @@ google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced/go.mod h1:SzzZ/N+n
google.golang.org/genproto v0.0.0-20210624174822-c5cf32407d0a/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210719143636-1d5a45f8e492/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210721163202-f1cecdd8b78a/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f h1:YORWxaStkWBnWgELOHTmDrqNlFXuVGEbhwbB5iK94bQ=
google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67 h1:VmMSf20ssFK0+u1dscyTH9bU4/M4y+X/xNfkvD6kGtM=
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
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=
@ -2427,9 +2426,8 @@ google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.39.0 h1:Klz8I9kdtkIN6EpHHUOMLCYhTn/2WAe5a0s1hcBkdTI=
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.39.1 h1:f37vZbBVTiJ6jKG5mWz8ySOBxNqy6ViPgyhSdVnxF3E=
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@ -2535,7 +2533,6 @@ k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo=
k8s.io/api v0.20.2/go.mod h1:d7n6Ehyzx+S+cE3VhTGfVNNqtGc/oL9DCdYYahlurV8=
k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ=
k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8=
k8s.io/api v0.20.7/go.mod h1:4x0yErUkcEWYG+O0S4QdrYa2+PLEeY2M7aeQe++2nmk=
k8s.io/api v0.21.1/go.mod h1:FstGROTmsSHBarKc8bylzXih8BLNYTiS3TZcsoEDg2s=
k8s.io/api v0.21.3 h1:cblWILbLO8ar+Fj6xdDGr603HRsf8Wu9E9rngJeprZQ=
k8s.io/api v0.21.3/go.mod h1:hUgeYHUbBp23Ue4qdX9tR8/ANi/g3ehylAqDn9NWVOg=
@ -2551,7 +2548,6 @@ k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRp
k8s.io/apimachinery v0.20.2/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc=
k8s.io/apimachinery v0.20.7/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc=
k8s.io/apimachinery v0.21.1/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY=
k8s.io/apimachinery v0.21.3 h1:3Ju4nvjCngxxMYby0BimUk+pQHPOQp3eCGChk5kfVII=
k8s.io/apimachinery v0.21.3/go.mod h1:H/IM+5vH9kZRNJ4l3x/fXP/5bOPJaVP/guptnZPeCFI=

View file

@ -22,6 +22,8 @@ func CreateElementHandler(element string, pattern interface{}, path string) Vali
switch {
case commonAnchors.IsConditionAnchor(element):
return NewConditionAnchorHandler(element, pattern, path)
case commonAnchors.IsGlobalAnchor(element):
return NewGlobalAnchorHandler(element, pattern, path)
case commonAnchors.IsExistenceAnchor(element):
return NewExistenceHandler(element, pattern, path)
case commonAnchors.IsEqualityAnchor(element):
@ -151,7 +153,8 @@ func (ch ConditionAnchorHandler) Handle(handler resourceElementHandler, resource
// validate the values of the pattern
returnPath, err := handler(log.Log, value, ch.pattern, originPattern, currentPath, ac)
if err != nil {
return returnPath, err
ac.AnchorError = common.NewConditionalAnchorError(fmt.Sprintf("condition anchor did not satisfy: %s", err.Error()))
return returnPath, ac.AnchorError.Error()
}
return "", nil
@ -159,6 +162,39 @@ func (ch ConditionAnchorHandler) Handle(handler resourceElementHandler, resource
return "", nil
}
//NewGlobalAnchorHandler returns an instance of condition acnhor handler
func NewGlobalAnchorHandler(anchor string, pattern interface{}, path string) ValidationHandler {
return GlobalAnchorHandler{
anchor: anchor,
pattern: pattern,
path: path,
}
}
//GlobalAnchorHandler provides handler for global condition anchor
type GlobalAnchorHandler struct {
anchor string
pattern interface{}
path string
}
//Handle processed global condition anchor
func (gh GlobalAnchorHandler) Handle(handler resourceElementHandler, resourceMap map[string]interface{}, originPattern interface{}, ac *common.AnchorKey) (string, error) {
anchorKey, _ := commonAnchors.RemoveAnchor(gh.anchor)
currentPath := gh.path + anchorKey + "/"
// check if anchor is present in resource
if value, ok := resourceMap[anchorKey]; ok {
// validate the values of the pattern
returnPath, err := handler(log.Log, value, gh.pattern, originPattern, currentPath, ac)
if err != nil {
ac.AnchorError = common.NewGlobalAnchorError(fmt.Sprintf("global anchor did not satisfy: %s", err.Error()))
return returnPath, ac.AnchorError.Error()
}
return "", nil
}
return "", nil
}
//NewExistenceHandler returns existence handler
func NewExistenceHandler(anchor string, pattern interface{}, path string) ValidationHandler {
return ExistenceHandler{

View file

@ -17,6 +17,24 @@ func IsConditionAnchor(str string) bool {
return (str[0] == '(' && str[len(str)-1] == ')')
}
//IsGlobalAnchor checks for global condition anchor
func IsGlobalAnchor(str string) bool {
left := "<("
right := ")"
if len(str) < len(left)+len(right) {
return false
}
//TODO: trim spaces ?
return (str[:len(left)] == left && str[len(str)-len(right):] == right)
}
//ContainsCondition returns true, if str is either condition anchor or
// global condition anchor
func ContainsCondition(str string) bool {
return IsConditionAnchor(str) || IsGlobalAnchor(str)
}
//IsNegationAnchor checks for negation anchor
func IsNegationAnchor(str string) bool {
left := "X("
@ -76,7 +94,7 @@ func RemoveAnchor(key string) (string, string) {
return key[1 : len(key)-1], key[0:1]
}
if IsExistenceAnchor(key) || IsAddingAnchor(key) || IsEqualityAnchor(key) || IsNegationAnchor(key) {
if IsExistenceAnchor(key) || IsAddingAnchor(key) || IsEqualityAnchor(key) || IsNegationAnchor(key) || IsGlobalAnchor(key) {
return key[2 : len(key)-1], key[0:2]
}

View file

@ -16,6 +16,11 @@ func IsConditionalAnchorError(msg string) bool {
return false
}
// IsGlobalAnchorError checks if error message has conditional anchor error string
func IsGlobalAnchorError(msg string) bool {
return strings.Contains(msg, GlobalAnchorErrMsg)
}
// NewConditionalAnchorError returns a new instance of ConditionalAnchorError
func NewConditionalAnchorError(msg string) ValidateAnchorError {
return ValidateAnchorError{
@ -26,10 +31,20 @@ func NewConditionalAnchorError(msg string) ValidateAnchorError {
// IsConditionAnchorError ...
func (e ValidateAnchorError) IsConditionAnchorError() bool {
if e.Err == ConditionalAnchorErr {
return true
return e.Err == ConditionalAnchorErr
}
return false
// NewGlobalAnchorError returns a new instance of GlobalAnchorError
func NewGlobalAnchorError(msg string) ValidateAnchorError {
return ValidateAnchorError{
Err: GlobalAnchorErr,
Message: fmt.Sprintf("%s: %s", GlobalAnchorErrMsg, msg),
}
}
// IsConditionAnchorError ...
func (e ValidateAnchorError) IsGlobalAnchorError() bool {
return e.Err == GlobalAnchorErr
}
// IsNil ...
@ -44,8 +59,13 @@ func (e ValidateAnchorError) Error() error {
// AnchorError is the const specification of anchor errors
type AnchorError int
// ConditionalAnchorErr ...
const ConditionalAnchorErr AnchorError = iota
const (
// ConditionalAnchorErr refers to condition violation
ConditionalAnchorErr AnchorError = iota
// GlobalAnchorErr refers to global condition violation
GlobalAnchorErr
)
// ValidateAnchorError represents the error type of validation anchors
type ValidateAnchorError struct {
@ -56,6 +76,9 @@ type ValidateAnchorError struct {
// ConditionalAnchorErrMsg - the error message for conditional anchor error
var ConditionalAnchorErrMsg = "conditionalAnchorError"
// GlobalAnchorErrMsg - the error message for global anchor error
var GlobalAnchorErrMsg = "globalAnchorError"
// AnchorKey - contains map of anchors
type AnchorKey struct {
// anchorMap - for each anchor key in the patterns it will maintains information if the key exists in the resource

View file

@ -4,7 +4,6 @@ import (
"bytes"
"encoding/json"
"fmt"
"reflect"
"time"
"github.com/go-logr/logr"
@ -30,26 +29,6 @@ func ProcessStrategicMergePatch(ruleName string, overlay interface{}, resource u
logger.V(4).Info("finished applying strategicMerge patch", "processingTime", resp.RuleStats.ProcessingTime.String())
}()
// ====== Meet Conditions =======
if path, overlayerr := meetConditions(log, resource.UnstructuredContent(), overlay); !reflect.DeepEqual(overlayerr, overlayError{}) {
switch overlayerr.statusCode {
// anchor key does not exist in the resource, skip applying policy
case conditionNotPresent:
log.V(4).Info("skip applying policy", "path", path, "error", overlayerr)
log.V(3).Info("skip applying rule", "reason", "conditionNotPresent")
resp.Success = true
return resp, resource
// anchor key is not satisfied in the resource, skip applying policy
case conditionFailure:
log.V(4).Info("failed to validate condition", "path", path, "error", overlayerr)
log.V(3).Info("skip applying rule", "reason", "conditionFailure")
resp.Success = true
resp.Message = overlayerr.ErrorMsg()
return resp, resource
}
}
// ============================
overlayBytes, err := json.Marshal(overlay)
if err != nil {
resp.Success = false
@ -99,15 +78,24 @@ func ProcessStrategicMergePatch(ruleName string, overlay interface{}, resource u
resp.Success = true
resp.Patches = jsonPatches
resp.Message = fmt.Sprintf("successfully processed strategic merge patch")
resp.Message = "successfully processed strategic merge patch"
return resp, patchedResource
}
func strategicMergePatch(logger logr.Logger, base, overlay string) ([]byte, error) {
preprocessedYaml, err := preProcessStrategicMergePatch(logger, overlay, base)
if err != nil {
_, isConditionError := err.(ConditionError)
_, isGlobalConditionError := err.(GlobalConditionError)
if isConditionError || isGlobalConditionError {
if err = preprocessedYaml.UnmarshalJSON([]byte(`{}`)); err != nil {
return []byte{}, err
}
} else {
return []byte{}, fmt.Errorf("failed to preProcess rule: %+v", err)
}
}
f := patchstrategicmerge.Filter{
Patch: preprocessedYaml,
@ -122,6 +110,8 @@ func strategicMergePatch(logger logr.Logger, base, overlay string) ([]byte, erro
func preProcessStrategicMergePatch(logger logr.Logger, pattern, resource string) (*yaml.RNode, error) {
patternNode := yaml.MustParse(pattern)
resourceNode := yaml.MustParse(resource)
err := preProcessPattern(logger, patternNode, resourceNode)
return patternNode, err
}

View file

@ -2,7 +2,6 @@ package mutate
import (
"encoding/json"
"fmt"
"testing"
kyvernov1 "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
@ -25,33 +24,149 @@ func TestMergePatch(t *testing.T) {
},
{
// condition matches the first element of the array
rawPolicy: []byte(`{"spec": {"containers": [{"(image)": "gcr.io/google-containers/busybox:*"}],"imagePullSecrets": [{"name": "regcred"}]}}`),
rawResource: []byte(`{"apiVersion": "v1","kind": "Pod","metadata": {"name": "hello"},"spec": {"containers": [{"name": "hello","image": "gcr.io/google-containers/busybox:latest"},{"name": "hello2","image": "gcr.io/google-containers/busybox:latest"},{"name": "hello3","image": "gcr.io/google-containers/nginx:latest"}]}}`),
expected: []byte(`{"apiVersion":"v1","kind":"Pod","metadata":{"name":"hello"},"spec":{"containers":[{"image":"gcr.io/google-containers/busybox:latest","name":"hello"},{"image":"gcr.io/google-containers/busybox:latest","name":"hello2"},{"image":"gcr.io/google-containers/nginx:latest","name":"hello3"}],"imagePullSecrets":[{"name":"regcred"}]}}`),
rawPolicy: []byte(`{
"spec": {
"containers": [
{
"(image)": "gcr.io/google-containers/busybox:*"
}
],
"imagePullSecrets": [
{
"name": "regcred"
}
]
}
}`),
rawResource: []byte(`{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "hello"
},
"spec": {
"containers": [
{
"name": "hello",
"image": "gcr.io/google-containers/busybox:latest"
},
{
"name": "hello2",
"image": "gcr.io/google-containers/busybox:latest"
},
{
"name": "hello3",
"image": "gcr.io/google-containers/nginx:latest"
}
]
}
}`),
expected: []byte(`{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "hello"
},
"spec": {
"containers": [
{
"image": "gcr.io/google-containers/busybox:latest",
"name": "hello"
},
{
"image": "gcr.io/google-containers/busybox:latest",
"name": "hello2"
},
{
"image": "gcr.io/google-containers/nginx:latest",
"name": "hello3"
}
],
"imagePullSecrets": [
{
"name": "regcred"
}
]
}
}`),
},
{
// condition matches the third element of the array
rawPolicy: []byte(`{"spec": {"containers": [{"(image)": "gcr.io/google-containers/nginx:*"}],"imagePullSecrets": [{"name": "regcred"}]}}`),
rawResource: []byte(`{"apiVersion": "v1","kind": "Pod","metadata": {"name": "hello"},"spec": {"containers": [{"name": "hello","image": "gcr.io/google-containers/busybox:latest"},{"name": "hello2","image": "gcr.io/google-containers/busybox:latest"},{"name": "hello3","image": "gcr.io/google-containers/nginx:latest"}]}}`),
expected: []byte(`{"apiVersion":"v1","kind":"Pod","metadata":{"name":"hello"},"spec":{"containers":[{"image":"gcr.io/google-containers/nginx:latest","name":"hello3"},{"image":"gcr.io/google-containers/busybox:latest","name":"hello"},{"image":"gcr.io/google-containers/busybox:latest","name":"hello2"}],"imagePullSecrets":[{"name":"regcred"}]}}`),
rawPolicy: []byte(`{
"spec": {
"containers": [
{
"(image)": "gcr.io/google-containers/nginx:*"
}
],
"imagePullSecrets": [
{
"name": "regcred"
}
]
}
}`),
rawResource: []byte(`{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "hello"
},
"spec": {
"containers": [
{
"name": "hello",
"image": "gcr.io/google-containers/busybox:latest"
},
{
"name": "hello2",
"image": "gcr.io/google-containers/busybox:latest"
},
{
"name": "hello3",
"image": "gcr.io/google-containers/nginx:latest"
}
]
}
}`),
expected: []byte(`{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "hello"
},
"spec": {
"containers": [
{
"image": "gcr.io/google-containers/busybox:latest",
"name": "hello"
},
{
"image": "gcr.io/google-containers/busybox:latest",
"name": "hello2"
},
{
"image": "gcr.io/google-containers/nginx:latest",
"name": "hello3"
}
],
"imagePullSecrets": [
{
"name": "regcred"
}
]
}
}`),
},
}
for i, test := range testCases {
// out
t.Logf("Running test %d...", i+1)
out, err := strategicMergePatch(log.Log, string(test.rawResource), string(test.rawPolicy))
assert.NilError(t, err)
// expect
var expectUnstr unstructured.Unstructured
err = json.Unmarshal(test.expected, &expectUnstr)
assert.NilError(t, err)
expectString, err := json.Marshal(expectUnstr.Object)
assert.NilError(t, err)
assertnew.Equal(t, string(expectString), string(out), fmt.Sprintf("test %v fails", i))
// has assertions inside
areEqualJSONs(t, test.expected, out)
}
}

View file

@ -15,13 +15,25 @@ type ConditionError struct {
}
func (ce ConditionError) Error() string {
return fmt.Sprintf("Condition failed: %s", ce.errorChain.Error())
return fmt.Sprintf("condition failed: %s", ce.errorChain.Error())
}
func NewConditionError(err error) error {
return ConditionError{err}
}
type GlobalConditionError struct {
errorChain error
}
func (ce GlobalConditionError) Error() string {
return fmt.Sprintf("global condition failed: %s", ce.errorChain.Error())
}
func NewGlobalConditionError(err error) error {
return GlobalConditionError{err}
}
// preProcessPattern - Dynamically preProcess the yaml
// 1> For conditional anchor remove anchors from the pattern.
// 2> For Adding anchors remove anchor tags.
@ -52,7 +64,6 @@ func preProcessRecursive(logger logr.Logger, pattern, resource *yaml.RNode) erro
return nil
}
// walkMap - walk through the MappingNode
func walkMap(logger logr.Logger, pattern, resource *yaml.RNode) error {
var err error
@ -66,24 +77,23 @@ func walkMap(logger logr.Logger, pattern, resource *yaml.RNode) error {
return err
}
fields, err := pattern.Fields()
nonAnchors, err := filterKeys(pattern, func(key string) bool {
return !hasAnchor(key)
})
if err != nil {
return err
}
for _, field := range fields {
var resourceNode *yaml.RNode
var resourceValue *yaml.RNode
for _, field := range nonAnchors {
if resource == nil || resource.Field(field) == nil {
// In case if we have pattern, but not corresponding resource part,
// just walk down and remove all anchors. nil here indicates that
// resourceNode is empty
resourceNode = nil
resourceValue = nil
} else {
resourceNode = resource.Field(field).Value
resourceValue = resource.Field(field).Value
}
err := preProcessRecursive(logger, pattern.Field(field).Value, resourceNode)
err := preProcessRecursive(logger, pattern.Field(field).Value, resourceValue)
if err != nil {
return err
}
@ -92,7 +102,6 @@ func walkMap(logger logr.Logger, pattern, resource *yaml.RNode) error {
return nil
}
// walkList - walk through array elements
func walkList(logger logr.Logger, pattern, resource *yaml.RNode) error {
elements, err := pattern.Elements()
if err != nil {
@ -127,17 +136,32 @@ func processListOfMaps(logger logr.Logger, pattern, resource *yaml.RNode) error
for _, patternElement := range patternElements {
// If pattern has conditions, look for matching elements and process them
if hasAnchors(patternElement) {
hasAnyAnchor := hasAnchors(patternElement, hasAnchor)
hasGlobalConditions := hasAnchors(patternElement, anchor.IsGlobalAnchor)
if hasAnyAnchor {
anyGlobalConditionPassed := false
var lastGlobalAnchorError error = nil
for _, resourceElement := range resourceElements {
err := preProcessRecursive(logger, patternElement, resourceElement)
if err != nil {
if _, ok := err.(ConditionError); ok {
switch err.(type) {
case ConditionError:
// Skip element, if condition has failed
continue
case GlobalConditionError:
lastGlobalAnchorError = err
continue
}
return err
} else {
if hasGlobalConditions {
// global anchor has passed, there is no need to return an error
anyGlobalConditionPassed = true
}
// If condition is satisfied, create new pattern list element based on patternElement
// but related with current resource element by name.
// Resource element must have name. Without name kustomize won't be able to update this element.
@ -148,11 +172,16 @@ func processListOfMaps(logger logr.Logger, pattern, resource *yaml.RNode) error
}
newNode := patternElement.Copy()
err := deleteConditionsFromNestedMaps(newNode)
empty, err := deleteConditionsFromNestedMaps(newNode)
if err != nil {
return err
}
// Do not add an empty element to the patch
if empty {
continue
}
err = newNode.PipeE(yaml.SetField("name", resourceElementName.Value))
if err != nil {
return err
@ -164,6 +193,10 @@ func processListOfMaps(logger logr.Logger, pattern, resource *yaml.RNode) error
}
}
}
if !anyGlobalConditionPassed && lastGlobalAnchorError != nil {
return lastGlobalAnchorError
}
}
}
@ -173,23 +206,18 @@ func processListOfMaps(logger logr.Logger, pattern, resource *yaml.RNode) error
// validateConditions checks all conditions from current map.
// If at least one condition fails, return error.
// If caller handles list of maps and gets an error, it must skip element.
// If caller handles list of maps and gets GlobalConditionError, it must skip entire rule.
// If caller handles map, it must stop processing and skip entire rule.
func validateConditions(logger logr.Logger, pattern, resource *yaml.RNode) error {
conditions, err := filterKeys(pattern, anchor.IsConditionAnchor)
var err error
err = validateConditionsInternal(logger, pattern, resource, anchor.IsGlobalAnchor)
if err != nil {
return err
return NewGlobalConditionError(err)
}
for _, condition := range conditions {
conditionKey := removeAnchor(condition)
if resource == nil || resource.Field(conditionKey) == nil {
continue
}
err = checkCondition(logger, pattern.Field(condition).Value, resource.Field(conditionKey).Value)
err = validateConditionsInternal(logger, pattern, resource, anchor.IsConditionAnchor)
if err != nil {
return err
}
return NewConditionError(err)
}
return nil
@ -239,7 +267,11 @@ func filterKeys(pattern *yaml.RNode, condition func(string) bool) ([]string, err
return keys, nil
}
func hasAnchors(pattern *yaml.RNode) bool {
func hasAnchor(key string) bool {
return anchor.ContainsCondition(key) || anchor.IsAddingAnchor(key)
}
func hasAnchors(pattern *yaml.RNode, isAnchor func(key string) bool) bool {
if yaml.MappingNode == pattern.YNode().Kind {
fields, err := pattern.Fields()
if err != nil {
@ -247,13 +279,13 @@ func hasAnchors(pattern *yaml.RNode) bool {
}
for _, key := range fields {
if anchor.IsConditionAnchor(key) || anchor.IsAddingAnchor(key) {
if isAnchor(key) {
return true
}
patternNode := pattern.Field(key)
if !patternNode.IsNilOrEmpty() {
if hasAnchors(patternNode.Value) {
if hasAnchors(patternNode.Value, isAnchor) {
return true
}
}
@ -304,41 +336,54 @@ func checkCondition(logger logr.Logger, pattern *yaml.RNode, resource *yaml.RNod
}
_, err = validate.ValidateResourceWithPattern(logger, resourceInterface, patternInterface)
if err != nil {
return NewConditionError(err)
return err
}
return nil
}
func deleteConditionsFromNestedMaps(pattern *yaml.RNode) error {
func deleteConditionsFromNestedMaps(pattern *yaml.RNode) (bool, error) {
if pattern.YNode().Kind != yaml.MappingNode {
return nil
return false, nil
}
fields, err := pattern.Fields()
if err != nil {
return err
return false, err
}
for _, field := range fields {
if anchor.IsConditionAnchor(field) {
if anchor.ContainsCondition(field) {
err = pattern.PipeE(yaml.Clear(field))
if err != nil {
return err
return false, err
}
} else {
child := pattern.Field(field).Value
if child != nil {
err = deleteConditionsFromNestedMaps(child)
empty, err := deleteConditionsFromNestedMaps(child)
if err != nil {
return err
return false, err
}
if empty {
err = pattern.PipeE(yaml.Clear(field))
if err != nil {
return false, err
}
}
}
}
}
return nil
fields, err = pattern.Fields()
if err != nil {
return false, err
}
if len(fields) == 0 {
return true, nil
}
return false, nil
}
func deleteConditionElements(pattern *yaml.RNode) error {
@ -381,7 +426,7 @@ func deleteAnchors(node *yaml.RNode) (bool, error) {
}
func deleteAnchorsInMap(node *yaml.RNode) (bool, error) {
conditions, err := filterKeys(node, anchor.IsConditionAnchor)
conditions, err := filterKeys(node, anchor.ContainsCondition)
if err != nil {
return false, err
}
@ -399,22 +444,28 @@ func deleteAnchorsInMap(node *yaml.RNode) (bool, error) {
return false, err
}
needToDelete := true
// Go further through the map elements.
hasOnlyAnchors := true
for _, field := range fields {
ok, err := deleteAnchors(node.Field(field).Value)
if err != nil {
return false, err
}
// If we have at least one element without annchor,
if ok {
err = node.PipeE(yaml.Clear(field))
if err != nil {
return false, err
}
} else {
// If we have at least one element without anchor,
// then we don't need to delete this element.
if !ok {
hasOnlyAnchors = false
needToDelete = false
}
}
return hasOnlyAnchors, nil
return needToDelete, nil
}
func deleteAnchorsInList(node *yaml.RNode) (bool, error) {
@ -423,8 +474,10 @@ func deleteAnchorsInList(node *yaml.RNode) (bool, error) {
return false, err
}
wasEmpty := len(elements) == 0
for i, element := range elements {
if hasAnchors(element) {
if hasAnchors(element, hasAnchor) {
deleteListElement(node, i)
} else {
// This element also could have some conditions
@ -434,9 +487,6 @@ func deleteAnchorsInList(node *yaml.RNode) (bool, error) {
if err != nil {
return false, err
}
if err != nil {
return false, err
}
if ok {
deleteListElement(node, i)
}
@ -447,7 +497,7 @@ func deleteAnchorsInList(node *yaml.RNode) (bool, error) {
if err != nil {
return false, err
}
if len(elements) == 0 {
if len(elements) == 0 && !wasEmpty {
return true, nil
}
@ -458,3 +508,24 @@ func deleteListElement(list *yaml.RNode, i int) {
content := list.YNode().Content
list.YNode().Content = append(content[:i], content[i+1:]...)
}
func validateConditionsInternal(logger logr.Logger, pattern, resource *yaml.RNode, filter func(string) bool) error {
conditions, err := filterKeys(pattern, filter)
if err != nil {
return err
}
for _, condition := range conditions {
conditionKey := removeAnchor(condition)
if resource == nil || resource.Field(conditionKey) == nil {
return fmt.Errorf("could not found \"%s\" key in the resource", conditionKey)
}
err = checkCondition(logger, pattern.Field(condition).Value, resource.Field(conditionKey).Value)
if err != nil {
return err
}
}
return nil
}

View file

@ -29,6 +29,59 @@ func Test_preProcessStrategicMergePatch_multipleAnchors(t *testing.T) {
rawResource []byte
expectedPatch []byte
}{
{
rawPolicy: []byte(`{
"metadata": {
"annotations": {
"+(cluster-autoscaler.kubernetes.io/safe-to-evict)": "true"
}
},
"spec": {
"volumes": [
{
"<(emptyDir)": {}
}
]
}
}`),
rawResource: []byte(`{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "static-web",
"labels": {
"role": "myrole"
}
},
"spec": {
"containers": [
{
"name": "web",
"image": "1nginx"
}
],
"volumes": [
{
"emptyDir": {},
"name": "cache-volume"
},
{
"secret": {
"secretName": "default-token-6gplg"
},
"name": "default-token-6gplg"
}
]
}
}`),
expectedPatch: []byte(`{
"metadata": {
"annotations": {
"cluster-autoscaler.kubernetes.io/safe-to-evict": "true"
}
}
}`),
},
{
rawPolicy: []byte(`{
"metadata": null
@ -177,11 +230,6 @@ func Test_preProcessStrategicMergePatch_multipleAnchors(t *testing.T) {
}`),
expectedPatch: []byte(`{
"spec": {
"containers": [
{
"name": "hello"
}
],
"imagePullSecrets": [
{
"name": "regcred"
@ -222,11 +270,6 @@ func Test_preProcessStrategicMergePatch_multipleAnchors(t *testing.T) {
}`),
expectedPatch: []byte(`{
"spec": {
"containers": [
{
"name": "hello"
}
],
"imagePullSecrets": [
{
"name": "regcred"
@ -276,14 +319,6 @@ func Test_preProcessStrategicMergePatch_multipleAnchors(t *testing.T) {
}`),
expectedPatch: []byte(`{
"spec": {
"containers": [
{
"name": "hello"
},
{
"name": "hello2"
}
],
"imagePullSecrets": [
{
"name": "regcred"
@ -351,13 +386,6 @@ func Test_preProcessStrategicMergePatch_multipleAnchors(t *testing.T) {
"labels": {
"add-labels": "add"
}
},
"spec": {
"volumes": [
{
"name": "cache-volume"
}
]
}
}`),
},
@ -412,15 +440,7 @@ func Test_preProcessStrategicMergePatch_multipleAnchors(t *testing.T) {
]
}
}`),
expectedPatch: []byte(`{
"spec": {
"volumes": [
{
"name": "cache-volume"
}
]
}
}`),
expectedPatch: []byte(`{}`),
},
{
rawPolicy: []byte(`{
@ -606,8 +626,7 @@ func Test_preProcessStrategicMergePatch_multipleAnchors(t *testing.T) {
"metadata": {
"annotations": {
"annotation2": "atest2"
},
"labels": {}
}
},
"spec": {
"containers": [
@ -686,52 +705,56 @@ func Test_preProcessStrategicMergePatch_multipleAnchors(t *testing.T) {
{
rawPolicy: []byte(`{
"metadata": {
"labels": {
"(key1)": "value1",
"annotations": {
"+(cluster-autoscaler.kubernetes.io/safe-to-evict)": true
}
},
"spec": {
"containers": [
"volumes": [
{
"name": "busybox",
"image": "gcr.io/google-containers/busybox:latest"
"hostPath": {
"<(path)": "*data"
}
],
"imagePullSecrets": [
{
"name": "regcred"
}
]
}
}`),
rawResource: []byte(`{
"apiVersion": "v1",
"kind": "Pod",
"apiVersion": "v1",
"metadata": {
"name": "hello"
"name": "nginx"
},
"spec": {
"containers": [
{
"name": "hello",
"image": "busybox"
"name": "nginx",
"image": "nginx:latest",
"imagePullPolicy": "Never",
"volumeMounts": [
{
"mountPath": "/cache",
"name": "cache-volume"
}
]
}
],
"volumes": [
{
"name": "cache-volume",
"hostPath": {
"path": "/data",
"type": "Directory"
}
}
]
}
}`),
expectedPatch: []byte(`{
"spec": {
"containers": [
{
"name": "busybox",
"image": "gcr.io/google-containers/busybox:latest"
"metadata": {
"annotations": {
"cluster-autoscaler.kubernetes.io/safe-to-evict": true
}
],
"imagePullSecrets": [
{
"name": "regcred"
}
]
}
}`),
},
@ -831,6 +854,7 @@ func Test_preProcessStrategicMergePatch_multipleAnchors(t *testing.T) {
}
for i, test := range testCases {
t.Logf("Running test %d...", i+1)
preProcessedPolicy, err := preProcessStrategicMergePatch(log.Log, string(test.rawPolicy), string(test.rawResource))
assert.NilError(t, err)
@ -900,7 +924,7 @@ func Test_CheckConditionAnchor_DoesNotMatch(t *testing.T) {
resource := yaml.MustParse(string(resourceRaw))
err := checkCondition(log.Log, pattern, resource)
assert.Error(t, err, "Condition failed: Validation rule failed at '/key1/' to validate value 'sample' with pattern 'value*'")
assert.Error(t, err, "Validation rule failed at '/key1/' to validate value 'sample' with pattern 'value*'")
}
func Test_ValidateConditions_MapWithOneCondition_Matches(t *testing.T) {
@ -1045,7 +1069,8 @@ func Test_ConditionCheck_SeveralElementsMatchExceptOne(t *testing.T) {
patternRaw := []byte(`{
"containers": [
{
"(image)": "gcr.io/google-containers/busybox:*"
"(name)": "hello?",
"image": "gcr.io/google-containers/busybox:1"
}
]
}`)
@ -1073,8 +1098,57 @@ func Test_ConditionCheck_SeveralElementsMatchExceptOne(t *testing.T) {
err := preProcessPattern(log.Log, pattern, containers)
assert.NilError(t, err)
containersElements, err := pattern.Field("containers").Value.Elements()
patternContainers := pattern.Field("containers")
assert.Assert(t, patternContainers != nil)
assert.Assert(t, patternContainers.Value != nil)
elements, err := patternContainers.Value.Elements()
assert.NilError(t, err)
assert.Equal(t, len(containersElements), 2)
assert.Equal(t, len(elements), 2)
}
func Test_NonExistingKeyMustFailPreprocessing(t *testing.T) {
rawPattern := []byte(`{
"metadata": {
"labels": {
"(key1)": "value1",
}
},
"spec": {
"containers": [
{
"name": "busybox",
"image": "gcr.io/google-containers/busybox:latest"
}
],
"imagePullSecrets": [
{
"name": "regcred"
}
]
}
}`)
rawResource := []byte(`{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "hello"
},
"spec": {
"containers": [
{
"name": "hello",
"image": "busybox"
}
]
}
}`)
pattern := yaml.MustParse(string(rawPattern))
resource := yaml.MustParse(string(rawResource))
err := preProcessPattern(log.Log, pattern, resource)
assert.Error(t, err, "condition failed: could not found \"key1\" key in the resource")
}

View file

@ -26,7 +26,7 @@ func removeAnchor(key string) string {
return key[1 : len(key)-1]
}
if commonAnchors.IsExistenceAnchor(key) || commonAnchors.IsAddingAnchor(key) || commonAnchors.IsEqualityAnchor(key) || commonAnchors.IsNegationAnchor(key) {
if commonAnchors.IsExistenceAnchor(key) || commonAnchors.IsAddingAnchor(key) || commonAnchors.IsEqualityAnchor(key) || commonAnchors.IsNegationAnchor(key) || commonAnchors.IsGlobalAnchor(key) {
return key[2 : len(key)-1]
}

View file

@ -7,7 +7,6 @@ import (
"github.com/go-logr/logr"
"github.com/kyverno/kyverno/pkg/engine/anchor"
commonAnchors "github.com/kyverno/kyverno/pkg/engine/anchor/common"
"github.com/kyverno/kyverno/pkg/engine/common"
"github.com/kyverno/kyverno/pkg/engine/operator"
"github.com/kyverno/kyverno/pkg/engine/wildcards"
@ -20,7 +19,8 @@ func ValidateResourceWithPattern(logger logr.Logger, resource, pattern interface
ac := common.NewAnchorMap()
elemPath, err := validateResourceElement(logger, resource, pattern, pattern, "/", ac)
if err != nil {
if common.IsConditionalAnchorError(err.Error()) {
if common.IsConditionalAnchorError(err.Error()) || common.IsGlobalAnchorError(err.Error()) {
logger.V(3).Info(ac.AnchorError.Message)
return "", nil
}
@ -102,12 +102,7 @@ func validateMap(log logr.Logger, resourceMap, patternMap map[string]interface{}
// if there are resource values at same level, then anchor acts as conditional instead of a strict check
// but if there are non then its a if then check
if err != nil {
// If Conditional anchor fails then we don't process the resources
if commonAnchors.IsConditionAnchor(key) {
ac.AnchorError = common.NewConditionalAnchorError(fmt.Sprintf("condition anchor did not satisfy: %s", err.Error()))
log.V(3).Info(ac.AnchorError.Message)
return "", ac.AnchorError.Error()
}
// If global anchor fails then we don't process the resource
return handlerPath, err
}
}

View file

@ -1394,6 +1394,11 @@ func TestConditionalAnchorWithMultiplePatterns(t *testing.T) {
pattern: []byte(`{"spec": {"containers": [{"name": "*","(image)": "*:latest | !*:*","imagePullPolicy": "!Always"}]}}`),
resource: []byte(`{"spec": {"containers": [{"name": "nginx","image": "nginx", "imagePullPolicy": "Always"}]}}`),
nilErr: false,
}, {
name: "check global anchor",
pattern: []byte(`{"spec": {"containers": [{"name": "*","<(image)": "*:latest","imagePullPolicy": "!Always"}]}}`),
resource: []byte(`{"spec": {"containers": [{"name": "nginx","image": "nginx", "imagePullPolicy": "Always"}]}}`),
nilErr: true,
},
{
name: "test-4",

View file

@ -31,7 +31,7 @@ func (v *Validate) Validate() (string, error) {
}
if rule.Pattern != nil {
if path, err := common.ValidatePattern(rule.Pattern, "/", []commonAnchors.IsAnchor{commonAnchors.IsConditionAnchor, commonAnchors.IsExistenceAnchor, commonAnchors.IsEqualityAnchor, commonAnchors.IsNegationAnchor}); err != nil {
if path, err := common.ValidatePattern(rule.Pattern, "/", []commonAnchors.IsAnchor{commonAnchors.IsConditionAnchor, commonAnchors.IsExistenceAnchor, commonAnchors.IsEqualityAnchor, commonAnchors.IsNegationAnchor, commonAnchors.IsGlobalAnchor}); err != nil {
return fmt.Sprintf("pattern.%s", path), err
}
}
@ -42,7 +42,7 @@ func (v *Validate) Validate() (string, error) {
return "anyPattern", fmt.Errorf("failed to deserialize anyPattern, expect array: %v", err)
}
for i, pattern := range anyPattern {
if path, err := common.ValidatePattern(pattern, "/", []commonAnchors.IsAnchor{commonAnchors.IsConditionAnchor, commonAnchors.IsExistenceAnchor, commonAnchors.IsEqualityAnchor, commonAnchors.IsNegationAnchor}); err != nil {
if path, err := common.ValidatePattern(pattern, "/", []commonAnchors.IsAnchor{commonAnchors.IsConditionAnchor, commonAnchors.IsExistenceAnchor, commonAnchors.IsEqualityAnchor, commonAnchors.IsNegationAnchor, commonAnchors.IsGlobalAnchor}); err != nil {
return fmt.Sprintf("anyPattern[%d].%s", i, path), err
}
}

View file

@ -21,7 +21,7 @@ spec:
+(cluster-autoscaler.kubernetes.io/safe-to-evict): "true"
spec:
volumes:
- (emptyDir): {}
- <(emptyDir): {}
- name: annotate-host-path
match:
resources:
@ -34,5 +34,5 @@ spec:
+(cluster-autoscaler.kubernetes.io/safe-to-evict): "true"
spec:
volumes:
- (hostPath):
path: "*"
- hostPath:
<(path): "*"

View file

@ -2,6 +2,7 @@ apiVersion: v1
kind: Pod
metadata:
name: pod-with-default-volume
creationTimestamp: "2020-09-21T12:56:35Z"
spec:
containers:
- image: k8s.gcr.io/test-webserver

View file

@ -2,6 +2,7 @@ apiVersion: v1
kind: Pod
metadata:
name: pod-with-default-volume
creationTimestamp: "2020-09-21T12:56:35Z"
spec:
containers:
- image: k8s.gcr.io/test-webserver

View file

@ -4,7 +4,7 @@ input:
resource: test/resources/pod-with-default-volume.yaml
expected:
mutation:
patchedresource: test/resources/pod-with-default-volume.yaml
patchedresource: test/output/pod-with-default-volume.yaml
policyresponse:
policy:
namespace: ''