diff --git a/go.mod b/go.mod index 150b99c40..0e7f8047a 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( github.com/k14s/kbld v0.32.0 github.com/lithammer/dedent v1.1.0 github.com/logrusorgru/aurora v2.0.3+incompatible + github.com/mattn/go-sqlite3 v1.14.16 github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.20.1 github.com/otiai10/copy v1.4.2 @@ -30,11 +31,11 @@ require ( github.com/tj/assert v0.0.3 github.com/vmware-tanzu/carvel-ytt v0.40.0 github.com/vmware-tanzu/tanzu-framework/apis/cli v0.0.0-20221205143842-a334b86a2650 - github.com/vmware-tanzu/tanzu-framework/capabilities/client v0.0.0-20221202212418-359f504ed815 + github.com/vmware-tanzu/tanzu-framework/capabilities/client v0.0.0-20230121092944-3710280bf92a github.com/vmware-tanzu/tanzu-plugin-runtime v0.0.0-20221207020746-9f818c753271 go.uber.org/multierr v1.8.0 golang.org/x/mod v0.6.0 - golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 + golang.org/x/oauth2 v0.3.0 google.golang.org/grpc v1.48.0 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 @@ -64,7 +65,7 @@ require ( github.com/docker/distribution v2.8.1+incompatible // indirect github.com/docker/docker v20.10.16+incompatible // indirect github.com/docker/docker-credential-helpers v0.6.4 // indirect - github.com/emicklei/go-restful/v3 v3.8.0 // indirect + github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect @@ -116,13 +117,13 @@ require ( github.com/vmware-tanzu/carvel-vendir v0.26.0 // indirect github.com/vmware-tanzu/tanzu-framework/apis/run v0.0.0-20221207131309-7323ca04b86c // indirect go.uber.org/atomic v1.9.0 // indirect - golang.org/x/crypto v0.1.0 // indirect - golang.org/x/net v0.2.0 // indirect + golang.org/x/crypto v0.3.0 // indirect + golang.org/x/net v0.4.0 // indirect golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect - golang.org/x/sys v0.2.0 // indirect - golang.org/x/term v0.2.0 // indirect - golang.org/x/text v0.4.0 // indirect - golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect + golang.org/x/sys v0.3.0 // indirect + golang.org/x/term v0.3.0 // indirect + golang.org/x/text v0.5.0 // indirect + golang.org/x/time v0.3.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20220810155839-1856144b1d9c // indirect @@ -132,10 +133,10 @@ require ( k8s.io/apiextensions-apiserver v0.25.0 // indirect k8s.io/component-base v0.25.0 // indirect k8s.io/klog/v2 v2.70.1 // indirect - k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect + k8s.io/kube-openapi v0.0.0-20221207184640-f3cff1453715 // indirect k8s.io/kubectl v0.24.0 // indirect k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect - sigs.k8s.io/cluster-api v1.2.7 // indirect + sigs.k8s.io/cluster-api v1.2.8 // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect diff --git a/go.sum b/go.sum index 952fbc912..02b20997f 100644 --- a/go.sum +++ b/go.sum @@ -303,8 +303,8 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= -github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -620,6 +620,8 @@ github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRC github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= @@ -898,8 +900,8 @@ github.com/vmware-tanzu/tanzu-framework/apis/cli v0.0.0-20221205143842-a334b86a2 github.com/vmware-tanzu/tanzu-framework/apis/cli v0.0.0-20221205143842-a334b86a2650/go.mod h1:R6Oc9N+xdv7CqDUYEniAhzzhKqAH9KAhGUnlikOGRg0= github.com/vmware-tanzu/tanzu-framework/apis/run v0.0.0-20221207131309-7323ca04b86c h1:w1b5UNbfqUetv4f32qqkbh2ESV+0iZCpMlq72zfyDqs= github.com/vmware-tanzu/tanzu-framework/apis/run v0.0.0-20221207131309-7323ca04b86c/go.mod h1:ukZpKQ0hf5bjWdJLjn2M6qXP+9giZWQPxt8nOfrCR+o= -github.com/vmware-tanzu/tanzu-framework/capabilities/client v0.0.0-20221202212418-359f504ed815 h1:uuwq0KWncphYB4LA+OAi/XYfUgJP+Q9PnWzYgtudNoY= -github.com/vmware-tanzu/tanzu-framework/capabilities/client v0.0.0-20221202212418-359f504ed815/go.mod h1:dBxtBhdSqmHHHKGq0WwllQVuklNzDsAeP130lVOvqsc= +github.com/vmware-tanzu/tanzu-framework/capabilities/client v0.0.0-20230121092944-3710280bf92a h1:4eFwBDBd3zDxUzPxewLMJx3evqKsqrRAYjFrQNOQvqE= +github.com/vmware-tanzu/tanzu-framework/capabilities/client v0.0.0-20230121092944-3710280bf92a/go.mod h1:rcIfoGpdav3evsyEMMzYH0xhGZOkIy+Ra3koypM8Aco= github.com/vmware-tanzu/tanzu-plugin-runtime v0.0.0-20221207020746-9f818c753271 h1:Ck7Fe+FGH1iPmkPJKBuen/K5n0A5adpAIHYb1hl2ntM= github.com/vmware-tanzu/tanzu-plugin-runtime v0.0.0-20221207020746-9f818c753271/go.mod h1:dylXEjg0RYFldLnOasGiOj4+QybRskmCjF5tyX/iTZk= github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= @@ -978,8 +980,8 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= @@ -1053,8 +1055,8 @@ golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1070,8 +1072,8 @@ golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 h1:lxqLZaMad/dJHMFZH0NiNpiEZI/nhgWhe4wgzpE+MuA= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8= +golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk= 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= @@ -1181,13 +1183,13 @@ golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -1195,15 +1197,15 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1466,8 +1468,8 @@ 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-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= +k8s.io/kube-openapi v0.0.0-20221207184640-f3cff1453715 h1:tBEbstoM+K0FiBV5KGAKQ0kuvf54v/hwpldiJt69w1s= +k8s.io/kube-openapi v0.0.0-20221207184640-f3cff1453715/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= k8s.io/kubectl v0.24.0 h1:nA+WtMLVdXUs4wLogGd1mPTAesnLdBpCVgCmz3I7dXo= k8s.io/kubectl v0.24.0/go.mod h1:pdXkmCyHiRTqjYfyUJiXtbVNURhv0/Q1TyRhy2d5ic0= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= @@ -1479,8 +1481,8 @@ k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/l k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/cluster-api v1.2.7 h1:LjdToomKcAaOh71b2TSKbOucZgkw6NQhwiVaGuidI6E= -sigs.k8s.io/cluster-api v1.2.7/go.mod h1:qLMSP/QUb0zwBXoXo2MmzV+YLyNQBkK7OwYEUDOQyQA= +sigs.k8s.io/cluster-api v1.2.8 h1:O0ZGyxGBeJaSWVptM7U0vTArAVlxCE5OtQItZ4OS2Y4= +sigs.k8s.io/cluster-api v1.2.8/go.mod h1:HmxYwjLGHia5yjFoMY8I03Ha4kXAB+VTJnHFhAmPVig= sigs.k8s.io/controller-runtime v0.13.1 h1:tUsRCSJVM1QQOOeViGeX3GMT3dQF1eePPw6sEE3xSlg= sigs.k8s.io/controller-runtime v0.13.1/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI= sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= diff --git a/pkg/carvelhelpers/fetcher.go b/pkg/carvelhelpers/fetcher.go index 1039e5886..bac155978 100644 --- a/pkg/carvelhelpers/fetcher.go +++ b/pkg/carvelhelpers/fetcher.go @@ -47,6 +47,22 @@ func DownloadImageBundleAndSaveFilesToTempDir(imageWithTag string) (string, erro return tmpDir, nil } +// DownloadDBImage reads a plain OCI image and saves its +// files to the specified location. +func DownloadDBImage(imageWithTag, destinationDir string) error { + reg, err := newRegistry() + if err != nil { + return errors.Wrapf(err, "unable to initialize registry") + } + + err = reg.DownloadImage(imageWithTag, destinationDir) + if err != nil { + return errors.Wrap(err, "error downloading image") + } + + return nil +} + // newRegistry returns a new registry object by also // taking into account for any custom registry or proxy // environment variable provided by the user diff --git a/pkg/common/constants.go b/pkg/common/constants.go index 47915a82a..77cd5b524 100644 --- a/pkg/common/constants.go +++ b/pkg/common/constants.go @@ -30,3 +30,9 @@ const ( // CoreName is the name of the core binary. const CoreName = "core" + +const ( + // CentralRepoDBFileName is the name of the DB file that is stored in + // the OCI image describing the content of the Central Repository + CentralRepoDBFileName = "central.db" +) diff --git a/pkg/discovery/oci.go b/pkg/discovery/oci.go index b55b02c58..208a5d531 100644 --- a/pkg/discovery/oci.go +++ b/pkg/discovery/oci.go @@ -10,9 +10,11 @@ import ( apimachineryjson "k8s.io/apimachinery/pkg/runtime/serializer/json" cliv1alpha1 "github.com/vmware-tanzu/tanzu-framework/apis/cli/v1alpha1" + "github.com/vmware-tanzu/tanzu-plugin-runtime/config" "github.com/vmware-tanzu/tanzu-cli/pkg/carvelhelpers" "github.com/vmware-tanzu/tanzu-cli/pkg/common" + "github.com/vmware-tanzu/tanzu-cli/pkg/constants" ) // OCIDiscovery is an artifact discovery endpoint utilizing OCI image @@ -27,8 +29,15 @@ type OCIDiscovery struct { image string } -// NewOCIDiscovery returns a new local repository. +// NewOCIDiscovery returns a new Discovery using the specified OCI image. func NewOCIDiscovery(name, image string) Discovery { + if config.IsFeatureActivated(constants.FeatureCentralRepository) { + return &OCIDiscoveryForCentralRepo{ + name: name, + image: image, + } + } + return &OCIDiscovery{ name: name, image: image, diff --git a/pkg/discovery/oci_central.go b/pkg/discovery/oci_central.go new file mode 100644 index 000000000..e90290813 --- /dev/null +++ b/pkg/discovery/oci_central.go @@ -0,0 +1,250 @@ +// Copyright 2022 VMware, Inc. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package discovery + +import ( + "database/sql" + "fmt" + "os" + "path" + "path/filepath" + "strings" + + // Import the sqlite3 driver + _ "github.com/mattn/go-sqlite3" + "github.com/pkg/errors" + + "github.com/vmware-tanzu/tanzu-cli/pkg/carvelhelpers" + "github.com/vmware-tanzu/tanzu-cli/pkg/catalog" + "github.com/vmware-tanzu/tanzu-cli/pkg/common" + "github.com/vmware-tanzu/tanzu-cli/pkg/distribution" + cliv1alpha1 "github.com/vmware-tanzu/tanzu-framework/apis/cli/v1alpha1" +) + +// OCIDiscoveryForCentralRepo is an artifact discovery endpoint utilizing an OCI image +// which contains an SQLite database listing all available plugins. +type OCIDiscoveryForCentralRepo struct { + // name is the name given to the discovery + name string + // image is an OCI compliant image. Which include DNS-compatible registry name, + // a valid URI path(MAY contain zero or more ‘/’) and a valid tag + // E.g., harbor.my-domain.local/tanzu-cli/plugins-manifest:latest + // This image contains a single SQLite database file. + image string +} + +// Structure of each row of the SQLite database +type centralRepoRow struct { + name string + target string + recommendedVersion string + version string + hidden string + description string + publisher string + vendor string + os string + arch string + digest string + uri string +} + +// Name of the discovery. +func (od *OCIDiscoveryForCentralRepo) Name() string { + return od.name +} + +// Type of the discovery. +func (od *OCIDiscoveryForCentralRepo) Type() string { + return common.DiscoveryTypeOCI +} + +// List available plugins. +func (od *OCIDiscoveryForCentralRepo) List() (plugins []Discovered, err error) { + dbFilePath, err := od.fetchContentDB() + if err != nil { + return nil, errors.Wrapf(err, "unable to fetch the content of discovery '%s'", od.Name()) + } + + return od.getPluginsFromDB(dbFilePath) +} + +// Describe a plugin. +func (od *OCIDiscoveryForCentralRepo) Describe(name string) (Discovered, error) { + return Discovered{}, errors.Errorf("NOT IMPLEMENTED") +} + +// fetchContentDB downloads the content DB to the cache directory and returns +// the path to the DB file to use. +func (od *OCIDiscoveryForCentralRepo) fetchContentDB() (string, error) { + // TODO(khouzam): Improve by checking if we really need to download again or if we can use the cache + pluginDBDir := filepath.Join(common.DefaultCacheDir, "plugin_db") + if err := carvelhelpers.DownloadDBImage(od.image, pluginDBDir); err != nil { + return "", errors.Wrapf(err, "failed to download OCI image from discovery '%s'", od.Name()) + } + return filepath.Join(pluginDBDir, common.CentralRepoDBFileName), nil +} + +// getPluginsFromDB returns all plugins found in the DB located at the specified dbFilePath +func (od *OCIDiscoveryForCentralRepo) getPluginsFromDB(dbFilePath string) ([]Discovered, error) { + db, err := sql.Open("sqlite3", dbFilePath) + if err != nil { + return nil, errors.Wrapf(err, "failed to open the DB for discovery '%s'", od.Name()) + } + defer db.Close() + + // We need to order the results properly because the logic of processRows() + // expects an ordering of PluginName, then Target, then Version. + // The column order must also match the order used in getNextRow(). + dbQuery := "SELECT PluginName,Target,RecommendedVersion,Version,Hidden,Description,Publisher,Vendor,OS,Architecture,Digest,URI FROM PluginBinaries ORDER BY PluginName,Target,Version;" + rows, err := db.Query(dbQuery) + if err != nil { + return nil, errors.Wrapf(err, "unable to setup DB query for discovery '%s'", od.Name()) + } + defer rows.Close() + + allPluginPtrs, err := od.processRows(rows) + if err != nil { + return nil, err + } + + // Convert from plugin pointers to plugins + // TODO(khouzam): continue optimizing by converting every call + // to using pointers + var allPlugins []Discovered + for _, pluginPtr := range allPluginPtrs { + allPlugins = append(allPlugins, *pluginPtr) + } + return allPlugins, nil +} + +func (od *OCIDiscoveryForCentralRepo) processRows(rows *sql.Rows) ([]*Discovered, error) { + // The central repository uses relative image URIs to be future-proof. + // Determine the image prefix from the Central Repository main image. + // E.g., if the main image is at project.registry.vmware.com/tanzu-cli/plugins/plugin_database:latest + // then the image prefix should be project.registry.vmware.com/tanzu-cli/plugins/ + imagePrefix := path.Dir(od.image) + + currentPluginID := "" + currentVersion := "" + var currentPlugin *Discovered + allPlugins := make([]*Discovered, 0) + var artifactList distribution.ArtifactList + var artifacts distribution.Artifacts + + for rows.Next() { + row, err := getNextRow(rows) + if err != nil { + return allPlugins, err + } + + target := convertTargetFromDB(row.target) + pluginIDFromRow := catalog.PluginNameTarget(row.name, target) + if currentPluginID != pluginIDFromRow { + // Found a new plugin. + // Store the current one in the array and prepare the new one. + if currentPlugin != nil { + artifacts[currentVersion] = artifactList + artifactList = distribution.ArtifactList{} + currentPlugin.Distribution = artifacts + allPlugins = appendPlugin(allPlugins, currentPlugin) + } + currentPluginID = pluginIDFromRow + + currentPlugin = &Discovered{ + Name: row.name, + Description: row.description, + RecommendedVersion: row.recommendedVersion, + InstalledVersion: "", // TODO(khouzam) + SupportedVersions: []string{}, + Optional: false, + Scope: common.PluginScopeStandalone, + Source: "Central Repository", + ContextName: "", // TODO(khouzam) this is used when creating the catalog. Concept needs updating + DiscoveryType: common.DiscoveryTypeOCI, + Target: target, + Status: common.PluginStatusNotInstalled, + } + currentVersion = "" + artifacts = distribution.Artifacts{} + } + + // Check if we have a new version + if currentVersion != row.version { + // This is a new version of our current plugin. Add it to the array of versions. + // We can do this without verifying if the version is already there because + // we have requested the list of plugins from the database ordered by version. + currentPlugin.SupportedVersions = append(currentPlugin.SupportedVersions, row.version) + + // Also store the list of artifacts for the previous version then start building + // the artifact list for the new version + if currentVersion != "" { + artifacts[currentVersion] = artifactList + artifactList = distribution.ArtifactList{} + } + currentVersion = row.version + } + + // The central repository uses relative URIs to be future-proof. + // Build the full URI before creating the artifact. + fullImagePath := fmt.Sprintf("%s/%s", imagePrefix, row.uri) + // Create the artifact for this row. + artifact := distribution.Artifact{ + Image: fullImagePath, + URI: "", + Digest: row.digest, + OS: row.os, + Arch: row.arch, + } + artifactList = append(artifactList, artifact) + } + // Don't forget to store the very last plugin we were building + artifacts[currentVersion] = artifactList + currentPlugin.Distribution = artifacts + allPlugins = appendPlugin(allPlugins, currentPlugin) + return allPlugins, rows.Err() +} + +func getNextRow(rows *sql.Rows) (*centralRepoRow, error) { + var row centralRepoRow + // The order of the fields MUST match the order specified in the + // SELECT query that generated the rows. + err := rows.Scan( + &row.name, + &row.target, + &row.recommendedVersion, + &row.version, + &row.hidden, + &row.description, + &row.publisher, + &row.vendor, + &row.os, + &row.arch, + &row.digest, + &row.uri, + ) + return &row, err +} + +func convertTargetFromDB(target string) cliv1alpha1.Target { + target = strings.ToLower(target) + if target == "global" { + target = "" + } + return cliv1alpha1.StringToTarget(target) +} + +func appendPlugin(allPlugins []*Discovered, plugin *Discovered) []*Discovered { + // Now that we are done gathering the information for the plugin + // we need to compute the recommendedVersion if it wasn't provided + // by the database + if err := SortVersions(plugin.SupportedVersions); err != nil { + fmt.Fprintf(os.Stderr, "error parsing supported versions for plugin %s: %v", plugin.Name, err) + } + if plugin.RecommendedVersion == "" { + plugin.RecommendedVersion = plugin.SupportedVersions[len(plugin.SupportedVersions)-1] + } + allPlugins = append(allPlugins, plugin) + return allPlugins +} diff --git a/pkg/fakes/registy.go b/pkg/fakes/registy.go index be9189428..ed485173b 100644 --- a/pkg/fakes/registy.go +++ b/pkg/fakes/registy.go @@ -4,6 +4,8 @@ package fakes import ( "sync" + "github.com/pkg/errors" + "github.com/vmware-tanzu/tanzu-cli/pkg/registry" ) @@ -64,6 +66,11 @@ type Registry struct { invocationsMutex sync.RWMutex } +// TODO(khouzam) +func (fake *Registry) DownloadImage(arg1 string, arg2 string) error { + return errors.Errorf("Unimplemented") +} + func (fake *Registry) DownloadBundle(arg1 string, arg2 string) error { fake.downloadBundleMutex.Lock() ret, specificReturn := fake.downloadBundleReturnsOnCall[len(fake.downloadBundleArgsForCall)] diff --git a/pkg/registry/client.go b/pkg/registry/client.go index 5ac814d0c..32f877a0c 100644 --- a/pkg/registry/client.go +++ b/pkg/registry/client.go @@ -153,15 +153,23 @@ func getAllFilesContentFromImage(image regv1.Image) (map[string][]byte, error) { // DownloadBundle downloads OCI bundle similar to `imgpkg pull -b` command // It is recommended to use this function when downloading imgpkg bundle because -// - During the air-gapped script, these plugin discovery packages are copied to a -// private registry with the `imgpkg copy` command -// - Downloading files directly from OCI image similar to `GetFiles` doesn't work -// because it doesn't update the `ImageLock` file when we download the package from -// different registry. And returns original ImageLock file. and as ImageLock file -// is pointing to original registry instead of private registry, image references -// does not point to the correct location - +// - During the air-gapped script, these plugin discovery packages are copied to a +// private registry with the `imgpkg copy` command +// - Downloading files directly from OCI image similar to `GetFiles` doesn't work +// because it doesn't update the `ImageLock` file when we download the package from +// different registry. And returns original ImageLock file. and as ImageLock file +// is pointing to original registry instead of private registry, image references +// does not point to the correct location func (r *registry) DownloadBundle(imageName, outputDir string) error { + return r.downloadBundleOrImage(imageName, outputDir, true) +} + +// DownloadImage downloads an OCI image similarly to the `imgpkg pull -i` command +func (r *registry) DownloadImage(imageName, outputDir string) error { + return r.downloadBundleOrImage(imageName, outputDir, false) +} + +func (r *registry) downloadBundleOrImage(imageName, outputDir string, isBundle bool) error { // Creating a dummy writer to capture the logs // currently this logs are not displayed or used directly var outputBuf, errorBuf bytes.Buffer @@ -169,8 +177,11 @@ func (r *registry) DownloadBundle(imageName, outputDir string) error { pullOptions := cmd.NewPullOptions(writerUI) pullOptions.OutputPath = outputDir - pullOptions.BundleFlags = cmd.BundleFlags{Bundle: imageName} - + if isBundle { + pullOptions.BundleFlags = cmd.BundleFlags{Bundle: imageName} + } else { + pullOptions.ImageFlags = cmd.ImageFlags{Image: imageName} + } if r.opts != nil { pullOptions.RegistryFlags = cmd.RegistryFlags{ CACertPaths: r.opts.CACertPaths, diff --git a/pkg/registry/interface.go b/pkg/registry/interface.go index 122e59600..ecef47a87 100644 --- a/pkg/registry/interface.go +++ b/pkg/registry/interface.go @@ -17,4 +17,6 @@ type Registry interface { // DownloadBundle downloads OCI bundle similar to `imgpkg pull -b` command // It is recommended to use this function when downloading imgpkg bundle DownloadBundle(imageName, outputDir string) error + // DownloadImage downloads an OCI image similarly to the `imgpkg pull -i` command + DownloadImage(imageName, outputDir string) error }