diff --git a/cmd/helm/chart.go b/cmd/helm/chart.go deleted file mode 100644 index adc874cfe..000000000 --- a/cmd/helm/chart.go +++ /dev/null @@ -1,49 +0,0 @@ -/* -Copyright The Helm Authors. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "io" - - "github.com/spf13/cobra" - - "helm.sh/helm/v3/pkg/action" -) - -const chartHelp = ` -This command consists of multiple subcommands to work with the chart cache. - -The subcommands can be used to push, pull, tag, list, or remove Helm charts. -` - -func newChartCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "chart", - Short: "push, pull, tag, or remove Helm charts", - Long: chartHelp, - Hidden: !FeatureGateOCI.IsEnabled(), - PersistentPreRunE: checkOCIFeatureGate(), - } - cmd.AddCommand( - newChartListCmd(cfg, out), - newChartExportCmd(cfg, out), - newChartPullCmd(cfg, out), - newChartPushCmd(cfg, out), - newChartRemoveCmd(cfg, out), - newChartSaveCmd(cfg, out), - ) - return cmd -} diff --git a/cmd/helm/chart_export.go b/cmd/helm/chart_export.go deleted file mode 100644 index 67caf08d7..000000000 --- a/cmd/helm/chart_export.go +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "io" - - "github.com/spf13/cobra" - - "helm.sh/helm/v3/cmd/helm/require" - "helm.sh/helm/v3/pkg/action" -) - -const chartExportDesc = ` -Export a chart stored in local registry cache. - -This will create a new directory with the name of -the chart, in a format that developers can modify -and check into source control if desired. -` - -func newChartExportCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { - client := action.NewChartExport(cfg) - - cmd := &cobra.Command{ - Use: "export [ref]", - Short: "export a chart to directory", - Long: chartExportDesc, - Args: require.MinimumNArgs(1), - Hidden: !FeatureGateOCI.IsEnabled(), - RunE: func(cmd *cobra.Command, args []string) error { - ref := args[0] - return client.Run(out, ref) - }, - } - - f := cmd.Flags() - f.StringVarP(&client.Destination, "destination", "d", ".", "location to write the chart.") - - return cmd -} diff --git a/cmd/helm/chart_list.go b/cmd/helm/chart_list.go deleted file mode 100644 index e81882ccc..000000000 --- a/cmd/helm/chart_list.go +++ /dev/null @@ -1,48 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "io" - - "github.com/spf13/cobra" - - "helm.sh/helm/v3/pkg/action" -) - -const chartListDesc = ` -List all charts in the local registry cache. - -Charts are sorted by ref name, alphabetically. -` - -func newChartListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { - chartList := action.NewChartList(cfg) - cmd := &cobra.Command{ - Use: "list", - Aliases: []string{"ls"}, - Short: "list all saved charts", - Long: chartListDesc, - Hidden: !FeatureGateOCI.IsEnabled(), - RunE: func(cmd *cobra.Command, args []string) error { - return chartList.Run(out) - }, - } - f := cmd.Flags() - f.UintVar(&chartList.ColumnWidth, "max-col-width", 60, "maximum column width for output table") - return cmd -} diff --git a/cmd/helm/chart_pull.go b/cmd/helm/chart_pull.go deleted file mode 100644 index 760ff3e2c..000000000 --- a/cmd/helm/chart_pull.go +++ /dev/null @@ -1,46 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "io" - - "github.com/spf13/cobra" - - "helm.sh/helm/v3/cmd/helm/require" - "helm.sh/helm/v3/pkg/action" -) - -const chartPullDesc = ` -Download a chart from a remote registry. - -This will store the chart in the local registry cache to be used later. -` - -func newChartPullCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { - return &cobra.Command{ - Use: "pull [ref]", - Short: "pull a chart from remote", - Long: chartPullDesc, - Args: require.MinimumNArgs(1), - Hidden: !FeatureGateOCI.IsEnabled(), - RunE: func(cmd *cobra.Command, args []string) error { - ref := args[0] - return action.NewChartPull(cfg).Run(out, ref) - }, - } -} diff --git a/cmd/helm/chart_push.go b/cmd/helm/chart_push.go deleted file mode 100644 index ff34632b1..000000000 --- a/cmd/helm/chart_push.go +++ /dev/null @@ -1,48 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "io" - - "github.com/spf13/cobra" - - "helm.sh/helm/v3/cmd/helm/require" - "helm.sh/helm/v3/pkg/action" -) - -const chartPushDesc = ` -Upload a chart to a remote registry. - -Note: the ref must already exist in the local registry cache. - -Must first run "helm chart save" or "helm chart pull". -` - -func newChartPushCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { - return &cobra.Command{ - Use: "push [ref]", - Short: "push a chart to remote", - Long: chartPushDesc, - Args: require.MinimumNArgs(1), - Hidden: !FeatureGateOCI.IsEnabled(), - RunE: func(cmd *cobra.Command, args []string) error { - ref := args[0] - return action.NewChartPush(cfg).Run(out, ref) - }, - } -} diff --git a/cmd/helm/chart_remove.go b/cmd/helm/chart_remove.go deleted file mode 100644 index d952951fb..000000000 --- a/cmd/helm/chart_remove.go +++ /dev/null @@ -1,50 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "io" - - "github.com/spf13/cobra" - - "helm.sh/helm/v3/cmd/helm/require" - "helm.sh/helm/v3/pkg/action" -) - -const chartRemoveDesc = ` -Remove a chart from the local registry cache. - -Note: the chart content will still exist in the cache, -but it will no longer appear in "helm chart list". - -To remove all unlinked content, please run "helm chart prune". (TODO) -` - -func newChartRemoveCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { - return &cobra.Command{ - Use: "remove [ref]", - Aliases: []string{"rm"}, - Short: "remove a chart", - Long: chartRemoveDesc, - Args: require.MinimumNArgs(1), - Hidden: !FeatureGateOCI.IsEnabled(), - RunE: func(cmd *cobra.Command, args []string) error { - ref := args[0] - return action.NewChartRemove(cfg).Run(out, ref) - }, - } -} diff --git a/cmd/helm/chart_save.go b/cmd/helm/chart_save.go deleted file mode 100644 index 35b72cd07..000000000 --- a/cmd/helm/chart_save.go +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "io" - "path/filepath" - - "github.com/spf13/cobra" - - "helm.sh/helm/v3/cmd/helm/require" - "helm.sh/helm/v3/pkg/action" - "helm.sh/helm/v3/pkg/chart/loader" -) - -const chartSaveDesc = ` -Store a copy of chart in local registry cache. - -Note: modifying the chart after this operation will -not change the item as it exists in the cache. -` - -func newChartSaveCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { - return &cobra.Command{ - Use: "save [path] [ref]", - Short: "save a chart directory", - Long: chartSaveDesc, - Args: require.MinimumNArgs(2), - Hidden: !FeatureGateOCI.IsEnabled(), - RunE: func(cmd *cobra.Command, args []string) error { - path := args[0] - ref := args[1] - - path, err := filepath.Abs(path) - if err != nil { - return err - } - - ch, err := loader.Load(path) - if err != nil { - return err - } - - return action.NewChartSave(cfg).Run(out, ch, ref) - }, - } -} diff --git a/cmd/helm/dependency_build_test.go b/cmd/helm/dependency_build_test.go index 33198a9dd..1f74cc955 100644 --- a/cmd/helm/dependency_build_test.go +++ b/cmd/helm/dependency_build_test.go @@ -45,7 +45,8 @@ func TestDependencyBuildCmd(t *testing.T) { ociChartName := "oci-depending-chart" c := createTestingMetadataForOCI(ociChartName, ociSrv.RegistryURL) - if err := chartutil.SaveDir(c, ociSrv.Dir); err != nil { + _, err = chartutil.Save(c, ociSrv.Dir) + if err != nil { t.Fatal(err) } ociSrv.Run(t, repotest.WithDependingChart(c)) @@ -136,6 +137,10 @@ func TestDependencyBuildCmd(t *testing.T) { } // OCI dependencies + err = chartutil.SaveDir(c, dir()) + if err != nil { + t.Fatal(err) + } cmd = fmt.Sprintf("dependency build '%s' --repository-config %s --repository-cache %s --registry-config %s/config.json", dir(ociChartName), dir("repositories.yaml"), diff --git a/cmd/helm/dependency_update_test.go b/cmd/helm/dependency_update_test.go index 9f7b0f303..8ee481f58 100644 --- a/cmd/helm/dependency_update_test.go +++ b/cmd/helm/dependency_update_test.go @@ -47,7 +47,8 @@ func TestDependencyUpdateCmd(t *testing.T) { ociChartName := "oci-depending-chart" c := createTestingMetadataForOCI(ociChartName, ociSrv.RegistryURL) - if err := chartutil.SaveDir(c, ociSrv.Dir); err != nil { + _, err = chartutil.Save(c, ociSrv.Dir) + if err != nil { t.Fatal(err) } ociSrv.Run(t, repotest.WithDependingChart(c)) @@ -134,6 +135,10 @@ func TestDependencyUpdateCmd(t *testing.T) { } // test for OCI charts + err = chartutil.SaveDir(c, dir()) + if err != nil { + t.Fatal(err) + } cmd := fmt.Sprintf("dependency update '%s' --repository-config %s --repository-cache %s --registry-config %s/config.json", dir(ociChartName), dir("repositories.yaml"), diff --git a/cmd/helm/install.go b/cmd/helm/install.go index fac2131c1..2d26615cc 100644 --- a/cmd/helm/install.go +++ b/cmd/helm/install.go @@ -19,6 +19,7 @@ package main import ( "io" "log" + "strings" "time" "github.com/pkg/errors" @@ -182,6 +183,12 @@ func runInstall(args []string, client *action.Install, valueOpts *values.Options } client.ReleaseName = name + if strings.HasPrefix(chart, "oci://") { + if !FeatureGateOCI.IsEnabled() { + return nil, FeatureGateOCI.Error() + } + } + cp, err := client.ChartPathOptions.LocateChart(chart, settings) if err != nil { return nil, err diff --git a/cmd/helm/push.go b/cmd/helm/push.go new file mode 100644 index 000000000..4b81b554e --- /dev/null +++ b/cmd/helm/push.go @@ -0,0 +1,63 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "fmt" + "io" + + "github.com/spf13/cobra" + + "helm.sh/helm/v3/cmd/helm/require" + "helm.sh/helm/v3/pkg/action" +) + +const pushDesc = ` +Upload a package to a registry. + +If the --with-prov flag is specified, the chart MUST have an associated +provenance file, which will also be uploaded. +` + +func newPushCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { + client := action.NewPushWithOpts(action.WithPushConfig(cfg)) + + cmd := &cobra.Command{ + Use: "push [chart] [remote]", + Short: "push a chart to remote", + Long: pushDesc, + Hidden: !FeatureGateOCI.IsEnabled(), + PersistentPreRunE: checkOCIFeatureGate(), + Args: require.MinimumNArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + chartRef := args[0] + remote := args[1] + client.Settings = settings + output, err := client.Run(chartRef, remote) + if err != nil { + return err + } + fmt.Fprint(out, output) + return nil + }, + } + + f := cmd.Flags() + f.BoolVar(&client.WithProv, "with-prov", false, "upload .prov file") + + return cmd +} diff --git a/cmd/helm/root.go b/cmd/helm/root.go index 285c80021..48f6e94bf 100644 --- a/cmd/helm/root.go +++ b/cmd/helm/root.go @@ -200,7 +200,7 @@ func newRootCmd(actionConfig *action.Configuration, out io.Writer, args []string // Add *experimental* subcommands cmd.AddCommand( newRegistryCmd(actionConfig, out), - newChartCmd(actionConfig, out), + newPushCmd(actionConfig, out), ) // Find and add plugins diff --git a/cmd/helm/show.go b/cmd/helm/show.go index 888d2d3f3..83d8668c7 100644 --- a/cmd/helm/show.go +++ b/cmd/helm/show.go @@ -20,6 +20,7 @@ import ( "fmt" "io" "log" + "strings" "github.com/spf13/cobra" @@ -176,6 +177,12 @@ func runShow(args []string, client *action.Show) (string, error) { client.Version = ">0.0.0-0" } + if strings.HasPrefix(args[0], "oci://") { + if !FeatureGateOCI.IsEnabled() { + return "", FeatureGateOCI.Error() + } + } + cp, err := client.ChartPathOptions.LocateChart(args[0], settings) if err != nil { return "", err diff --git a/cmd/helm/upgrade.go b/cmd/helm/upgrade.go index 1952b8421..cd5acd85d 100644 --- a/cmd/helm/upgrade.go +++ b/cmd/helm/upgrade.go @@ -20,6 +20,7 @@ import ( "fmt" "io" "log" + "strings" "time" "github.com/pkg/errors" @@ -82,6 +83,12 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { return nil, cobra.ShellCompDirectiveNoFileComp }, RunE: func(cmd *cobra.Command, args []string) error { + if strings.HasPrefix(args[1], "oci://") { + if !FeatureGateOCI.IsEnabled() { + return FeatureGateOCI.Error() + } + } + client.Namespace = settings.Namespace() // Fixes #7002 - Support reading values from STDIN for `upgrade` command diff --git a/go.mod b/go.mod index 12f211004..ae8970ab8 100644 --- a/go.mod +++ b/go.mod @@ -10,12 +10,10 @@ require ( github.com/Masterminds/squirrel v1.5.0 github.com/Masterminds/vcs v1.13.1 github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 - github.com/containerd/containerd v1.4.4 + github.com/containerd/containerd v1.5.2 github.com/cyphar/filepath-securejoin v0.2.2 - github.com/deislabs/oras v0.11.1 github.com/docker/distribution v2.7.1+incompatible github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible - github.com/docker/go-units v0.4.0 github.com/evanphx/json-patch v4.9.0+incompatible github.com/gobwas/glob v0.2.3 github.com/gofrs/flock v0.8.0 @@ -24,8 +22,8 @@ require ( github.com/lib/pq v1.10.0 github.com/mattn/go-shellwords v1.0.11 github.com/mitchellh/copystructure v1.1.1 - github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.0.1 + github.com/oras-project/oras-go v0.3.0-rc1 github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/pkg/errors v0.9.1 github.com/rubenv/sql-migrate v0.0.0-20200616145509-8d140a17f351 @@ -34,7 +32,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.7.0 github.com/xeipuuv/gojsonschema v1.2.0 - golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 + golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d k8s.io/api v0.21.0 k8s.io/apiextensions-apiserver v0.21.0 diff --git a/go.sum b/go.sum index b5268076e..a86a1be98 100644 --- a/go.sum +++ b/go.sum @@ -30,12 +30,15 @@ github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= github.com/Azure/go-autorest/autorest v0.11.12 h1:gI8ytXbxMfI+IVbI9mP2JGCTXIuhHLgRlvQ9X4PsnHE= github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= +github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= github.com/Azure/go-autorest/autorest/adal v0.9.5 h1:Y3bBUV4rTuxenJJs41HU3qmqsb+auo+a3Lz+PlJPpL0= github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE= @@ -60,11 +63,25 @@ github.com/Masterminds/squirrel v1.5.0 h1:JukIZisrUXadA9pl3rMkjhiamxiB0cXiu+HGp/ github.com/Masterminds/squirrel v1.5.0/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= github.com/Masterminds/vcs v1.13.1 h1:NL3G1X7/7xduQtA2sJLpVpfHTNBALVNSjob6KEjPXNQ= github.com/Masterminds/vcs v1.13.1/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHSmwVJjcKA= +github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/hcsshim v0.8.14 h1:lbPVK25c1cu5xTLITwpUcxoA9vKrKErASPYygvouJns= +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 h1:iT12IBVClFevaf8PuVyi3UmZOVh4OqnaLxDTW2O6j3w= +github.com/Microsoft/go-winio v0.4.17/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= +github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= +github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= +github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= +github.com/Microsoft/hcsshim v0.8.16 h1:8/auA4LFIZFTGrqfKhGBSXwM6/4X1fHa/xniyEHu8ac= +github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= +github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= +github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -84,6 +101,7 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= @@ -109,10 +127,12 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/bshuster-repo/logrus-logstash-hook v0.4.1 h1:pgAtgj+A31JBVtEHu2uHuEx0n+2ukqUJnS2vVe5pQNA= github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= @@ -127,37 +147,117 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= +github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= +github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= +github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= +github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59 h1:qWj4qVYZ95vLWwqyNJCQg7rDsG5wPdze0UaPolH7DUk= +github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= +github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= +github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= +github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= +github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= +github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= +github.com/containerd/cgroups v1.0.1 h1:iJnMvco9XGvKUvNQkv88bE4uJXxRQH18efbKo9w5vHQ= +github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= +github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= +github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.4 h1:rtRG4N6Ct7GNssATwgpvMGfnjnwfjnu/Zs9W3Ikzq+M= -github.com/containerd/containerd v1.4.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= +github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= +github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= +github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= +github.com/containerd/containerd v1.5.2 h1:MG/Bg1pbmMb61j3wHCFWPxESXHieiKr2xG64px/k8zQ= +github.com/containerd/containerd v1.5.2/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7 h1:6ejg6Lkk8dskcM7wQ28gONkukbQkM4qpj4RnYbpFzrI= +github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= +github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= +github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8= +github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= +github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= +github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= +github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= +github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= +github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= +github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= +github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= +github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= +github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= +github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= +github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= +github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= +github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= +github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= +github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= +github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= +github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= +github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= @@ -171,20 +271,22 @@ github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg= 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= +github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= +github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= -github.com/deislabs/oras v0.11.1 h1:oo2J/3vXdcti8cjFi8ghMOkx0OacONxHC8dhJ17NdJ0= -github.com/deislabs/oras v0.11.1/go.mod h1:39lCtf8Q6WDC7ul9cnyWXONNzKvabEKk+AX+L0ImnQk= github.com/denisenkom/go-mssqldb v0.0.0-20191001013358-cfbb681360f0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= -github.com/docker/cli v20.10.5+incompatible h1:bjflayQbWg+xOkF2WPEAOi4Y7zWhR7ptoPhV/VqLVDE= -github.com/docker/cli v20.10.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v20.10.7+incompatible h1:pv/3NqibQKphWZiAskMzdz8w0PRbtTaEB+f6NwdU7Is= +github.com/docker/cli v20.10.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v0.0.0-20191216044856-a8371794149d h1:jC8tT/S0OGx2cswpeUTn4gOIea8P08lD3VFQT0cOZ50= github.com/docker/distribution v0.0.0-20191216044856-a8371794149d/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible h1:iWPIG7pWIsCwT6ZtHnTUpoVMnete7O/pzd9HFE3+tn8= @@ -193,13 +295,17 @@ github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGl github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916 h1:yWHOI+vFjEsAakUTSrtqc/SAHrhSkmn48pqjidZX3QA= +github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= +github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4= github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -212,7 +318,9 @@ github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkg 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/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +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= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= @@ -226,11 +334,15 @@ github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTg github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7 h1:LofdAjjjqCSXMwLGgOgnE+rdPuvX9DxCqaHwKy7i/ko= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= @@ -312,14 +424,21 @@ github.com/gobuffalo/packr/v2 v2.7.1 h1:n3CIW5T17T8v4GGK5sWXLVWJhCz7b5aNLSxW6gYi github.com/gobuffalo/packr/v2 v2.7.1/go.mod h1:qYEvAazPaVxy7Y7KR0W8qYEE+RymX74kETFqjFoFlOc= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godror/godror v0.13.3/go.mod h1:2ouUT4kdhUBk7TAkHWD4SN0CdI0pgEQbo8FVHhbSKWg= github.com/gofrs/flock v0.8.0 h1:MSdYClljsF3PbENUUEx85nkWfJSGfzYI9yEBZOJz6CY= github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= +github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -341,6 +460,7 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -360,8 +480,10 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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= @@ -376,8 +498,9 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I= @@ -406,10 +529,12 @@ github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBt github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= @@ -426,18 +551,20 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -459,12 +586,16 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.13 h1:eSvu8Tmq6j2psUJqJrLcWH6K3w5Dwc+qipbaA6eVEN4= +github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -503,6 +634,7 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.11 h1:vCoR9VPpsk/TZFW2JwK5I9S0xdrtUq2bph6/YjEPnaw= github.com/mattn/go-shellwords v1.0.11/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-sqlite3 v1.12.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= @@ -512,6 +644,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 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= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.1.1 h1:Bp6x9R1Wn16SIz3OfeDr0b7RnCG2OB66Y7PQyC/cvq4= @@ -530,8 +664,15 @@ github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQ github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE= github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.4.1 h1:1O+1cHA1aujwEwwVMa2Xm2l+gIpUHyd3+D+d7LZh1kM= +github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk= github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -544,6 +685,7 @@ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -558,6 +700,8 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= 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/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= @@ -565,27 +709,46 @@ github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:v github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= +github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA= +github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= 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= +github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc93 h1:x2UMpOOVf3kQ8arv/EsDGwim8PTNqzL1/EYDr/+scOM= +github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= +github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= +github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= +github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -594,10 +757,13 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/oras-project/oras-go v0.3.0-rc1 h1:kaNwM3hf8eFYbEZJ54oVylCECcEXCSPu3DN3QYvxKWA= +github.com/oras-project/oras-go v0.3.0-rc1/go.mod h1:iGamc9+xWzQodKeX5l7FF0VgmmJ8aTRS2kJA6CedmjU= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= @@ -606,6 +772,7 @@ github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rK github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -619,6 +786,7 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -635,6 +803,7 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= @@ -642,11 +811,15 @@ github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -662,9 +835,11 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= @@ -672,6 +847,8 @@ github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXY github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +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= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -707,13 +884,16 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -722,19 +902,33 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +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/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= +github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/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/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= @@ -759,6 +953,7 @@ go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3C go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -776,7 +971,9 @@ go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -791,10 +988,12 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -830,6 +1029,7 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -858,10 +1058,14 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210224082022-3d97a244fca7 h1:OgUuv8lsRpBibGNbSizVwKWlysjaNzmC9gYMhPVfqFM= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 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= @@ -874,9 +1078,11 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -893,40 +1099,61 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073 h1:8qxJSnu+7dRq6upnbntrmriWByIakBuct5OM/MdQC1M= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492 h1:Paq34FxTluEPvVyayQqMPgHm+vTOrIifmcYxFBx9TLg= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= @@ -942,6 +1169,7 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/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-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1021,6 +1249,7 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= @@ -1030,6 +1259,7 @@ google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= @@ -1048,10 +1278,14 @@ google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1063,6 +1297,7 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1072,9 +1307,9 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8X gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/gorp.v1 v1.7.2 h1:j3DWlAyGVv8whO7AcIWznQ2Yj7yJkn34B8s63GViAAw= gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= @@ -1083,6 +1318,8 @@ gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= @@ -1110,38 +1347,61 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= +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.21.0 h1:gu5iGF4V6tfVCQ/R+8Hc0h7H1JuEhzyEi9S4R5LM8+Y= k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU= k8s.io/apiextensions-apiserver v0.21.0 h1:Nd4uBuweg6ImzbxkC1W7xUNZcCV/8Vt10iTdTIVF3hw= k8s.io/apiextensions-apiserver v0.21.0/go.mod h1:gsQGNtGkc/YoDG9loKI0V+oLZM4ljRPjc/sql5tmvzc= +k8s.io/apimachinery v0.20.1/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.21.0 h1:3Fx+41if+IRavNcKOz09FwEXDBG6ORh6iMsTSelhkMA= k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= +k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= +k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= +k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= k8s.io/apiserver v0.21.0 h1:1hWMfsz+cXxB77k6/y0XxWxwl6l9OF26PC9QneUVn1Q= k8s.io/apiserver v0.21.0/go.mod h1:w2YSn4/WIwYuxG5zJmcqtRdtqgW/J2JRgFAqps3bBpg= k8s.io/cli-runtime v0.21.0 h1:/V2Kkxtf6x5NI2z+Sd/mIrq4FQyQ8jzZAUD6N5RnN7Y= k8s.io/cli-runtime v0.21.0/go.mod h1:XoaHP93mGPF37MkLbjGVYqg3S1MnsFdKtiA/RZzzxOo= +k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= +k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= +k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= k8s.io/client-go v0.21.0 h1:n0zzzJsAQmJngpC0IhgFcApZyoGXPrDIAD601HD09ag= k8s.io/client-go v0.21.0/go.mod h1:nNBytTF9qPFDEhoqgEPaarobC8QPae13bElIVHzIglA= k8s.io/code-generator v0.21.0/go.mod h1:hUlps5+9QaTrKx+jiM4rmq7YmH8wPOIko64uZCHDh6Q= +k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= +k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= +k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= k8s.io/component-base v0.21.0 h1:tLLGp4BBjQaCpS/KiuWh7m2xqvAdsxLm4ATxHSe5Zpg= k8s.io/component-base v0.21.0/go.mod h1:qvtjz6X0USWXbgmbfXR+Agik4RZ3jv2Bgr5QnZzdPYw= k8s.io/component-helpers v0.21.0/go.mod h1:tezqefP7lxfvJyR+0a+6QtVrkZ/wIkyMLK4WcQ3Cj8U= +k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= +k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.8.0 h1:Q3gmuM9hKEjefWFFYF0Mat+YyFJvsUyYuwyNNJ5C9Ts= k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7 h1:vEx13qjvaZ4yfObSSXW7BrMc/KQBBT/Jyee8XtLf4x0= k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= k8s.io/kubectl v0.21.0 h1:WZXlnG/yjcE4LWO2g6ULjFxtzK6H1TKzsfaBFuVIhNg= k8s.io/kubectl v0.21.0/go.mod h1:EU37NukZRXn1TpAkMUoy8Z/B2u6wjHDS4aInsDzVvks= +k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/metrics v0.21.0/go.mod h1:L3Ji9EGPP1YBbfm9sPfEXSpnj8i24bfQbAFAsW0NueQ= k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +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/kustomize/api v0.8.5 h1:bfCXGXDAbFbb/Jv5AhMj2BB8a5VAJuuQ5/KU69WtDjQ= sigs.k8s.io/kustomize/api v0.8.5/go.mod h1:M377apnKT5ZHJS++6H4rQoCHmWtt6qTpp3mbe7p6OLY= @@ -1150,6 +1410,7 @@ sigs.k8s.io/kustomize/kustomize/v4 v4.0.5/go.mod h1:C7rYla7sI8EnxHE/xEhRBSHMNfcL sigs.k8s.io/kustomize/kyaml v0.10.15 h1:dSLgG78KyaxN4HylPXdK+7zB3k7sW6q3IcCmcfKA+aI= sigs.k8s.io/kustomize/kyaml v0.10.15/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.1.0 h1:C4r9BgJ98vrKnnVCjwCSXcWjWe0NKcUQkmzDXZXGwH8= sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/internal/experimental/registry/cache.go b/internal/experimental/registry/cache.go deleted file mode 100644 index 5aca63668..000000000 --- a/internal/experimental/registry/cache.go +++ /dev/null @@ -1,368 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package registry // import "helm.sh/helm/v3/internal/experimental/registry" - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "time" - - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" - orascontent "github.com/deislabs/oras/pkg/content" - digest "github.com/opencontainers/go-digest" - specs "github.com/opencontainers/image-spec/specs-go" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" - - "helm.sh/helm/v3/pkg/chart" - "helm.sh/helm/v3/pkg/chart/loader" - "helm.sh/helm/v3/pkg/chartutil" -) - -const ( - // CacheRootDir is the root directory for a cache - CacheRootDir = "cache" -) - -type ( - // Cache handles local/in-memory storage of Helm charts, compliant with OCI Layout - Cache struct { - debug bool - out io.Writer - rootDir string - ociStore *orascontent.OCIStore - memoryStore *orascontent.Memorystore - } - - // CacheRefSummary contains as much info as available describing a chart reference in cache - // Note: fields here are sorted by the order in which they are set in FetchReference method - CacheRefSummary struct { - Name string - Repo string - Tag string - Exists bool - Manifest *ocispec.Descriptor - Config *ocispec.Descriptor - ContentLayer *ocispec.Descriptor - Size int64 - Digest digest.Digest - CreatedAt time.Time - Chart *chart.Chart - } -) - -// NewCache returns a new OCI Layout-compliant cache with config -func NewCache(opts ...CacheOption) (*Cache, error) { - cache := &Cache{ - out: ioutil.Discard, - } - for _, opt := range opts { - opt(cache) - } - // validate - if cache.rootDir == "" { - return nil, errors.New("must set cache root dir on initialization") - } - return cache, nil -} - -// FetchReference retrieves a chart ref from cache -func (cache *Cache) FetchReference(ref *Reference) (*CacheRefSummary, error) { - if err := cache.init(); err != nil { - return nil, err - } - r := CacheRefSummary{ - Name: ref.FullName(), - Repo: ref.Repo, - Tag: ref.Tag, - } - for _, desc := range cache.ociStore.ListReferences() { - if desc.Annotations[ocispec.AnnotationRefName] == r.Name { - r.Exists = true - manifestBytes, err := cache.fetchBlob(&desc) - if err != nil { - return &r, err - } - var manifest ocispec.Manifest - err = json.Unmarshal(manifestBytes, &manifest) - if err != nil { - return &r, err - } - r.Manifest = &desc - r.Config = &manifest.Config - numLayers := len(manifest.Layers) - if numLayers != 1 { - return &r, errors.New( - fmt.Sprintf("manifest does not contain exactly 1 layer (total: %d)", numLayers)) - } - var contentLayer *ocispec.Descriptor - for _, layer := range manifest.Layers { - switch layer.MediaType { - case HelmChartContentLayerMediaType: - contentLayer = &layer - } - } - if contentLayer == nil { - return &r, errors.New( - fmt.Sprintf("manifest does not contain a layer with mediatype %s", HelmChartContentLayerMediaType)) - } - if contentLayer.Size == 0 { - return &r, errors.New( - fmt.Sprintf("manifest layer with mediatype %s is of size 0", HelmChartContentLayerMediaType)) - } - r.ContentLayer = contentLayer - info, err := cache.ociStore.Info(ctx(cache.out, cache.debug), contentLayer.Digest) - if err != nil { - return &r, err - } - r.Size = info.Size - r.Digest = info.Digest - r.CreatedAt = info.CreatedAt - contentBytes, err := cache.fetchBlob(contentLayer) - if err != nil { - return &r, err - } - ch, err := loader.LoadArchive(bytes.NewBuffer(contentBytes)) - if err != nil { - return &r, err - } - r.Chart = ch - } - } - return &r, nil -} - -// StoreReference stores a chart ref in cache -func (cache *Cache) StoreReference(ref *Reference, ch *chart.Chart) (*CacheRefSummary, error) { - if err := cache.init(); err != nil { - return nil, err - } - r := CacheRefSummary{ - Name: ref.FullName(), - Repo: ref.Repo, - Tag: ref.Tag, - Chart: ch, - } - existing, _ := cache.FetchReference(ref) - r.Exists = existing.Exists - config, _, err := cache.saveChartConfig(ch) - if err != nil { - return &r, err - } - r.Config = config - contentLayer, _, err := cache.saveChartContentLayer(ch) - if err != nil { - return &r, err - } - r.ContentLayer = contentLayer - info, err := cache.ociStore.Info(ctx(cache.out, cache.debug), contentLayer.Digest) - if err != nil { - return &r, err - } - r.Size = info.Size - r.Digest = info.Digest - r.CreatedAt = info.CreatedAt - manifest, _, err := cache.saveChartManifest(config, contentLayer) - if err != nil { - return &r, err - } - r.Manifest = manifest - return &r, nil -} - -// DeleteReference deletes a chart ref from cache -// TODO: garbage collection, only manifest removed -func (cache *Cache) DeleteReference(ref *Reference) (*CacheRefSummary, error) { - if err := cache.init(); err != nil { - return nil, err - } - r, err := cache.FetchReference(ref) - if err != nil || !r.Exists { - return r, err - } - cache.ociStore.DeleteReference(r.Name) - err = cache.ociStore.SaveIndex() - return r, err -} - -// ListReferences lists all chart refs in a cache -func (cache *Cache) ListReferences() ([]*CacheRefSummary, error) { - if err := cache.init(); err != nil { - return nil, err - } - var rr []*CacheRefSummary - for _, desc := range cache.ociStore.ListReferences() { - name := desc.Annotations[ocispec.AnnotationRefName] - if name == "" { - if cache.debug { - fmt.Fprintf(cache.out, "warning: found manifest without name: %s", desc.Digest.Hex()) - } - continue - } - ref, err := ParseReference(name) - if err != nil { - return rr, err - } - r, err := cache.FetchReference(ref) - if err != nil { - return rr, err - } - rr = append(rr, r) - } - return rr, nil -} - -// AddManifest provides a manifest to the cache index.json -func (cache *Cache) AddManifest(ref *Reference, manifest *ocispec.Descriptor) error { - if err := cache.init(); err != nil { - return err - } - cache.ociStore.AddReference(ref.FullName(), *manifest) - err := cache.ociStore.SaveIndex() - return err -} - -// Provider provides a valid containerd Provider -func (cache *Cache) Provider() content.Provider { - return content.Provider(cache.ociStore) -} - -// Ingester provides a valid containerd Ingester -func (cache *Cache) Ingester() content.Ingester { - return content.Ingester(cache.ociStore) -} - -// ProvideIngester provides a valid oras ProvideIngester -func (cache *Cache) ProvideIngester() orascontent.ProvideIngester { - return orascontent.ProvideIngester(cache.ociStore) -} - -// init creates files needed necessary for OCI layout store -func (cache *Cache) init() error { - if cache.ociStore == nil { - ociStore, err := orascontent.NewOCIStore(cache.rootDir) - if err != nil { - return err - } - cache.ociStore = ociStore - cache.memoryStore = orascontent.NewMemoryStore() - } - return nil -} - -// saveChartConfig stores the Chart.yaml as json blob and returns a descriptor -func (cache *Cache) saveChartConfig(ch *chart.Chart) (*ocispec.Descriptor, bool, error) { - configBytes, err := json.Marshal(ch.Metadata) - if err != nil { - return nil, false, err - } - configExists, err := cache.storeBlob(configBytes) - if err != nil { - return nil, configExists, err - } - descriptor := cache.memoryStore.Add("", HelmChartConfigMediaType, configBytes) - return &descriptor, configExists, nil -} - -// saveChartContentLayer stores the chart as tarball blob and returns a descriptor -func (cache *Cache) saveChartContentLayer(ch *chart.Chart) (*ocispec.Descriptor, bool, error) { - destDir := filepath.Join(cache.rootDir, ".build") - os.MkdirAll(destDir, 0755) - tmpFile, err := chartutil.Save(ch, destDir) - defer os.Remove(tmpFile) - if err != nil { - return nil, false, errors.Wrap(err, "failed to save") - } - contentBytes, err := ioutil.ReadFile(tmpFile) - if err != nil { - return nil, false, err - } - contentExists, err := cache.storeBlob(contentBytes) - if err != nil { - return nil, contentExists, err - } - descriptor := cache.memoryStore.Add("", HelmChartContentLayerMediaType, contentBytes) - return &descriptor, contentExists, nil -} - -// saveChartManifest stores the chart manifest as json blob and returns a descriptor -func (cache *Cache) saveChartManifest(config *ocispec.Descriptor, contentLayer *ocispec.Descriptor) (*ocispec.Descriptor, bool, error) { - manifest := ocispec.Manifest{ - Versioned: specs.Versioned{SchemaVersion: 2}, - Config: *config, - Layers: []ocispec.Descriptor{*contentLayer}, - } - manifestBytes, err := json.Marshal(manifest) - if err != nil { - return nil, false, err - } - manifestExists, err := cache.storeBlob(manifestBytes) - if err != nil { - return nil, manifestExists, err - } - descriptor := ocispec.Descriptor{ - MediaType: ocispec.MediaTypeImageManifest, - Digest: digest.FromBytes(manifestBytes), - Size: int64(len(manifestBytes)), - } - return &descriptor, manifestExists, nil -} - -// storeBlob stores a blob on filesystem -func (cache *Cache) storeBlob(blobBytes []byte) (bool, error) { - var exists bool - writer, err := cache.ociStore.Store.Writer(ctx(cache.out, cache.debug), - content.WithRef(digest.FromBytes(blobBytes).Hex())) - if err != nil { - return exists, err - } - _, err = writer.Write(blobBytes) - if err != nil { - return exists, err - } - err = writer.Commit(ctx(cache.out, cache.debug), 0, writer.Digest()) - if err != nil { - if !errdefs.IsAlreadyExists(err) { - return exists, err - } - exists = true - } - err = writer.Close() - return exists, err -} - -// fetchBlob retrieves a blob from filesystem -func (cache *Cache) fetchBlob(desc *ocispec.Descriptor) ([]byte, error) { - reader, err := cache.ociStore.ReaderAt(ctx(cache.out, cache.debug), *desc) - if err != nil { - return nil, err - } - defer reader.Close() - - bytes := make([]byte, desc.Size) - _, err = reader.ReadAt(bytes, 0) - if err != nil { - return nil, err - } - return bytes, nil -} diff --git a/internal/experimental/registry/cache_opts.go b/internal/experimental/registry/cache_opts.go deleted file mode 100644 index 6851ae807..000000000 --- a/internal/experimental/registry/cache_opts.go +++ /dev/null @@ -1,48 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package registry // import "helm.sh/helm/v3/internal/experimental/registry" - -import ( - "io" -) - -type ( - // CacheOption allows specifying various settings configurable by the user for overriding the defaults - // used when creating a new default cache - CacheOption func(*Cache) -) - -// CacheOptDebug returns a function that sets the debug setting on cache options set -func CacheOptDebug(debug bool) CacheOption { - return func(cache *Cache) { - cache.debug = debug - } -} - -// CacheOptWriter returns a function that sets the writer setting on cache options set -func CacheOptWriter(out io.Writer) CacheOption { - return func(cache *Cache) { - cache.out = out - } -} - -// CacheOptRoot returns a function that sets the root directory setting on cache options set -func CacheOptRoot(rootDir string) CacheOption { - return func(cache *Cache) { - cache.rootDir = rootDir - } -} diff --git a/internal/experimental/registry/client.go b/internal/experimental/registry/client.go deleted file mode 100644 index 26556533c..000000000 --- a/internal/experimental/registry/client.go +++ /dev/null @@ -1,341 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package registry // import "helm.sh/helm/v3/internal/experimental/registry" - -import ( - "bytes" - "context" - "fmt" - "io" - "io/ioutil" - "net/http" - "sort" - - auth "github.com/deislabs/oras/pkg/auth/docker" - "github.com/deislabs/oras/pkg/content" - "github.com/deislabs/oras/pkg/oras" - "github.com/gosuri/uitable" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" - - "helm.sh/helm/v3/pkg/chart" - "helm.sh/helm/v3/pkg/helmpath" -) - -const ( - // CredentialsFileBasename is the filename for auth credentials file - CredentialsFileBasename = "config.json" -) - -type ( - // Client works with OCI-compliant registries and local Helm chart cache - Client struct { - debug bool - // path to repository config file e.g. ~/.docker/config.json - credentialsFile string - out io.Writer - authorizer *Authorizer - resolver *Resolver - cache *Cache - columnWidth uint - } -) - -// NewClient returns a new registry client with config -func NewClient(opts ...ClientOption) (*Client, error) { - client := &Client{ - out: ioutil.Discard, - } - for _, opt := range opts { - opt(client) - } - // set defaults if fields are missing - if client.credentialsFile == "" { - client.credentialsFile = helmpath.CachePath("registry", CredentialsFileBasename) - } - if client.authorizer == nil { - authClient, err := auth.NewClient(client.credentialsFile) - if err != nil { - return nil, err - } - client.authorizer = &Authorizer{ - Client: authClient, - } - } - if client.resolver == nil { - resolver, err := client.authorizer.Resolver(context.Background(), http.DefaultClient, false) - if err != nil { - return nil, err - } - client.resolver = &Resolver{ - Resolver: resolver, - } - } - if client.cache == nil { - cache, err := NewCache( - CacheOptDebug(client.debug), - CacheOptWriter(client.out), - CacheOptRoot(helmpath.CachePath("registry", CacheRootDir)), - ) - if err != nil { - return nil, err - } - client.cache = cache - } - - if client.columnWidth == 0 { - client.columnWidth = 60 - } - return client, nil -} - -// Login logs into a registry -func (c *Client) Login(hostname string, username string, password string, insecure bool) error { - err := c.authorizer.Login(ctx(c.out, c.debug), hostname, username, password, insecure) - if err != nil { - return err - } - fmt.Fprintf(c.out, "Login succeeded\n") - return nil -} - -// Logout logs out of a registry -func (c *Client) Logout(hostname string) error { - err := c.authorizer.Logout(ctx(c.out, c.debug), hostname) - if err != nil { - return err - } - fmt.Fprintln(c.out, "Logout succeeded") - return nil -} - -// PushChart uploads a chart to a registry -func (c *Client) PushChart(ref *Reference) error { - r, err := c.cache.FetchReference(ref) - if err != nil { - return err - } - if !r.Exists { - return errors.New(fmt.Sprintf("Chart not found: %s", r.Name)) - } - fmt.Fprintf(c.out, "The push refers to repository [%s]\n", r.Repo) - c.printCacheRefSummary(r) - layers := []ocispec.Descriptor{*r.ContentLayer} - _, err = oras.Push(ctx(c.out, c.debug), c.resolver, r.Name, c.cache.Provider(), layers, - oras.WithConfig(*r.Config), oras.WithNameValidation(nil)) - if err != nil { - return err - } - s := "" - numLayers := len(layers) - if 1 < numLayers { - s = "s" - } - fmt.Fprintf(c.out, - "%s: pushed to remote (%d layer%s, %s total)\n", r.Tag, numLayers, s, byteCountBinary(r.Size)) - return nil -} - -// PullChart downloads a chart from a registry -func (c *Client) PullChart(ref *Reference) (*bytes.Buffer, error) { - buf := bytes.NewBuffer(nil) - - if ref.Tag == "" { - return buf, errors.New("tag explicitly required") - } - - fmt.Fprintf(c.out, "%s: Pulling from %s\n", ref.Tag, ref.Repo) - - store := content.NewMemoryStore() - fullname := ref.FullName() - _ = fullname - _, layerDescriptors, err := oras.Pull(ctx(c.out, c.debug), c.resolver, ref.FullName(), store, - oras.WithPullEmptyNameAllowed(), - oras.WithAllowedMediaTypes(KnownMediaTypes())) - if err != nil { - return buf, err - } - - numLayers := len(layerDescriptors) - if numLayers < 1 { - return buf, errors.New( - fmt.Sprintf("manifest does not contain at least 1 layer (total: %d)", numLayers)) - } - - var contentLayer *ocispec.Descriptor - for _, layer := range layerDescriptors { - layer := layer - switch layer.MediaType { - case HelmChartContentLayerMediaType: - contentLayer = &layer - - } - } - - if contentLayer == nil { - return buf, errors.New( - fmt.Sprintf("manifest does not contain a layer with mediatype %s", - HelmChartContentLayerMediaType)) - } - - _, b, ok := store.Get(*contentLayer) - if !ok { - return buf, errors.Errorf("Unable to retrieve blob with digest %s", contentLayer.Digest) - } - - buf = bytes.NewBuffer(b) - return buf, nil -} - -// PullChartToCache pulls a chart from an OCI Registry to the Registry Cache. -// This function is needed for `helm chart pull`, which is experimental and will be deprecated soon. -// Likewise, the Registry cache will soon be deprecated as will this function. -func (c *Client) PullChartToCache(ref *Reference) error { - if ref.Tag == "" { - return errors.New("tag explicitly required") - } - existing, err := c.cache.FetchReference(ref) - if err != nil { - return err - } - fmt.Fprintf(c.out, "%s: Pulling from %s\n", ref.Tag, ref.Repo) - manifest, _, err := oras.Pull(ctx(c.out, c.debug), c.resolver, ref.FullName(), c.cache.Ingester(), - oras.WithPullEmptyNameAllowed(), - oras.WithAllowedMediaTypes(KnownMediaTypes()), - oras.WithContentProvideIngester(c.cache.ProvideIngester())) - if err != nil { - return err - } - err = c.cache.AddManifest(ref, &manifest) - if err != nil { - return err - } - r, err := c.cache.FetchReference(ref) - if err != nil { - return err - } - if !r.Exists { - return errors.New(fmt.Sprintf("Chart not found: %s", r.Name)) - } - c.printCacheRefSummary(r) - if !existing.Exists { - fmt.Fprintf(c.out, "Status: Downloaded newer chart for %s\n", ref.FullName()) - } else { - fmt.Fprintf(c.out, "Status: Chart is up to date for %s\n", ref.FullName()) - } - return err -} - -// SaveChart stores a copy of chart in local cache -func (c *Client) SaveChart(ch *chart.Chart, ref *Reference) error { - r, err := c.cache.StoreReference(ref, ch) - if err != nil { - return err - } - c.printCacheRefSummary(r) - err = c.cache.AddManifest(ref, r.Manifest) - if err != nil { - return err - } - fmt.Fprintf(c.out, "%s: saved\n", r.Tag) - return nil -} - -// LoadChart retrieves a chart object by reference -func (c *Client) LoadChart(ref *Reference) (*chart.Chart, error) { - r, err := c.cache.FetchReference(ref) - if err != nil { - return nil, err - } - if !r.Exists { - return nil, errors.New(fmt.Sprintf("Chart not found: %s", ref.FullName())) - } - c.printCacheRefSummary(r) - return r.Chart, nil -} - -// RemoveChart deletes a locally saved chart -func (c *Client) RemoveChart(ref *Reference) error { - r, err := c.cache.DeleteReference(ref) - if err != nil { - return err - } - if !r.Exists { - return errors.New(fmt.Sprintf("Chart not found: %s", ref.FullName())) - } - fmt.Fprintf(c.out, "%s: removed\n", r.Tag) - return nil -} - -// PrintChartTable prints a list of locally stored charts -func (c *Client) PrintChartTable() error { - table := uitable.New() - table.MaxColWidth = c.columnWidth - table.AddRow("REF", "NAME", "VERSION", "DIGEST", "SIZE", "CREATED") - rows, err := c.getChartTableRows() - if err != nil { - return err - } - for _, row := range rows { - table.AddRow(row...) - } - fmt.Fprintln(c.out, table.String()) - return nil -} - -// printCacheRefSummary prints out chart ref summary -func (c *Client) printCacheRefSummary(r *CacheRefSummary) { - fmt.Fprintf(c.out, "ref: %s\n", r.Name) - fmt.Fprintf(c.out, "digest: %s\n", r.Manifest.Digest.Hex()) - fmt.Fprintf(c.out, "size: %s\n", byteCountBinary(r.Size)) - fmt.Fprintf(c.out, "name: %s\n", r.Chart.Metadata.Name) - fmt.Fprintf(c.out, "version: %s\n", r.Chart.Metadata.Version) -} - -// getChartTableRows returns rows in uitable-friendly format -func (c *Client) getChartTableRows() ([][]interface{}, error) { - rr, err := c.cache.ListReferences() - if err != nil { - return nil, err - } - refsMap := map[string]map[string]string{} - for _, r := range rr { - refsMap[r.Name] = map[string]string{ - "name": r.Chart.Metadata.Name, - "version": r.Chart.Metadata.Version, - "digest": shortDigest(r.Manifest.Digest.Hex()), - "size": byteCountBinary(r.Size), - "created": timeAgo(r.CreatedAt), - } - } - // Sort and convert to format expected by uitable - rows := make([][]interface{}, len(refsMap)) - keys := make([]string, 0, len(refsMap)) - for key := range refsMap { - keys = append(keys, key) - } - sort.Strings(keys) - for i, key := range keys { - rows[i] = make([]interface{}, 6) - rows[i][0] = key - ref := refsMap[key] - for j, k := range []string{"name", "version", "digest", "size", "created"} { - rows[i][j+1] = ref[k] - } - } - return rows, nil -} diff --git a/internal/experimental/registry/client_test.go b/internal/experimental/registry/client_test.go deleted file mode 100644 index a9936ba13..000000000 --- a/internal/experimental/registry/client_test.go +++ /dev/null @@ -1,294 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package registry - -import ( - "bytes" - "context" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/http/httptest" - "net/url" - "os" - "path/filepath" - "strings" - "testing" - "time" - - "github.com/containerd/containerd/errdefs" - auth "github.com/deislabs/oras/pkg/auth/docker" - "github.com/docker/distribution/configuration" - "github.com/docker/distribution/registry" - _ "github.com/docker/distribution/registry/auth/htpasswd" - _ "github.com/docker/distribution/registry/storage/driver/inmemory" - "github.com/phayes/freeport" - "github.com/stretchr/testify/suite" - "golang.org/x/crypto/bcrypt" - - "helm.sh/helm/v3/pkg/chart" -) - -var ( - testCacheRootDir = "helm-registry-test" - testHtpasswdFileBasename = "authtest.htpasswd" - testUsername = "myuser" - testPassword = "mypass" -) - -type RegistryClientTestSuite struct { - suite.Suite - Out io.Writer - DockerRegistryHost string - CompromisedRegistryHost string - CacheRootDir string - RegistryClient *Client -} - -func (suite *RegistryClientTestSuite) SetupSuite() { - suite.CacheRootDir = testCacheRootDir - os.RemoveAll(suite.CacheRootDir) - os.Mkdir(suite.CacheRootDir, 0700) - - var out bytes.Buffer - suite.Out = &out - credentialsFile := filepath.Join(suite.CacheRootDir, CredentialsFileBasename) - - client, err := auth.NewClient(credentialsFile) - suite.Nil(err, "no error creating auth client") - - resolver, err := client.Resolver(context.Background(), http.DefaultClient, false) - suite.Nil(err, "no error creating resolver") - - // create cache - cache, err := NewCache( - CacheOptDebug(true), - CacheOptWriter(suite.Out), - CacheOptRoot(filepath.Join(suite.CacheRootDir, CacheRootDir)), - ) - suite.Nil(err, "no error creating cache") - - // init test client - suite.RegistryClient, err = NewClient( - ClientOptDebug(true), - ClientOptWriter(suite.Out), - ClientOptAuthorizer(&Authorizer{ - Client: client, - }), - ClientOptResolver(&Resolver{ - Resolver: resolver, - }), - ClientOptCache(cache), - ) - suite.Nil(err, "no error creating registry client") - - // create htpasswd file (w BCrypt, which is required) - pwBytes, err := bcrypt.GenerateFromPassword([]byte(testPassword), bcrypt.DefaultCost) - suite.Nil(err, "no error generating bcrypt password for test htpasswd file") - htpasswdPath := filepath.Join(suite.CacheRootDir, testHtpasswdFileBasename) - err = ioutil.WriteFile(htpasswdPath, []byte(fmt.Sprintf("%s:%s\n", testUsername, string(pwBytes))), 0644) - suite.Nil(err, "no error creating test htpasswd file") - - // Registry config - config := &configuration.Configuration{} - port, err := freeport.GetFreePort() - suite.Nil(err, "no error finding free port for test registry") - suite.DockerRegistryHost = fmt.Sprintf("localhost:%d", port) - config.HTTP.Addr = fmt.Sprintf(":%d", port) - config.HTTP.DrainTimeout = time.Duration(10) * time.Second - config.Storage = map[string]configuration.Parameters{"inmemory": map[string]interface{}{}} - config.Auth = configuration.Auth{ - "htpasswd": configuration.Parameters{ - "realm": "localhost", - "path": htpasswdPath, - }, - } - dockerRegistry, err := registry.NewRegistry(context.Background(), config) - suite.Nil(err, "no error creating test registry") - - suite.CompromisedRegistryHost = initCompromisedRegistryTestServer() - - // Start Docker registry - go dockerRegistry.ListenAndServe() -} - -func (suite *RegistryClientTestSuite) TearDownSuite() { - os.RemoveAll(suite.CacheRootDir) -} - -func (suite *RegistryClientTestSuite) Test_0_Login() { - err := suite.RegistryClient.Login(suite.DockerRegistryHost, "badverybad", "ohsobad", false) - suite.NotNil(err, "error logging into registry with bad credentials") - - err = suite.RegistryClient.Login(suite.DockerRegistryHost, "badverybad", "ohsobad", true) - suite.NotNil(err, "error logging into registry with bad credentials, insecure mode") - - err = suite.RegistryClient.Login(suite.DockerRegistryHost, testUsername, testPassword, false) - suite.Nil(err, "no error logging into registry with good credentials") - - err = suite.RegistryClient.Login(suite.DockerRegistryHost, testUsername, testPassword, true) - suite.Nil(err, "no error logging into registry with good credentials, insecure mode") -} - -func (suite *RegistryClientTestSuite) Test_1_SaveChart() { - ref, err := ParseReference(fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost)) - suite.Nil(err) - - // empty chart - err = suite.RegistryClient.SaveChart(&chart.Chart{}, ref) - suite.NotNil(err) - - // valid chart - ch := &chart.Chart{} - ch.Metadata = &chart.Metadata{ - APIVersion: "v1", - Name: "testchart", - Version: "1.2.3", - } - err = suite.RegistryClient.SaveChart(ch, ref) - suite.Nil(err) -} - -func (suite *RegistryClientTestSuite) Test_2_LoadChart() { - - // non-existent ref - ref, err := ParseReference(fmt.Sprintf("%s/testrepo/whodis:9.9.9", suite.DockerRegistryHost)) - suite.Nil(err) - _, err = suite.RegistryClient.LoadChart(ref) - suite.NotNil(err) - - // existing ref - ref, err = ParseReference(fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost)) - suite.Nil(err) - ch, err := suite.RegistryClient.LoadChart(ref) - suite.Nil(err) - suite.Equal("testchart", ch.Metadata.Name) - suite.Equal("1.2.3", ch.Metadata.Version) -} - -func (suite *RegistryClientTestSuite) Test_3_PushChart() { - - // non-existent ref - ref, err := ParseReference(fmt.Sprintf("%s/testrepo/whodis:9.9.9", suite.DockerRegistryHost)) - suite.Nil(err) - err = suite.RegistryClient.PushChart(ref) - suite.NotNil(err) - - // existing ref - ref, err = ParseReference(fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost)) - suite.Nil(err) - err = suite.RegistryClient.PushChart(ref) - suite.Nil(err) -} - -func (suite *RegistryClientTestSuite) Test_4_PullChart() { - - // non-existent ref - ref, err := ParseReference(fmt.Sprintf("%s/testrepo/whodis:9.9.9", suite.DockerRegistryHost)) - suite.Nil(err) - _, err = suite.RegistryClient.PullChart(ref) - suite.NotNil(err) - - // existing ref - ref, err = ParseReference(fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost)) - suite.Nil(err) - _, err = suite.RegistryClient.PullChart(ref) - suite.Nil(err) -} - -func (suite *RegistryClientTestSuite) Test_5_PrintChartTable() { - err := suite.RegistryClient.PrintChartTable() - suite.Nil(err) -} - -func (suite *RegistryClientTestSuite) Test_6_RemoveChart() { - - // non-existent ref - ref, err := ParseReference(fmt.Sprintf("%s/testrepo/whodis:9.9.9", suite.DockerRegistryHost)) - suite.Nil(err) - err = suite.RegistryClient.RemoveChart(ref) - suite.NotNil(err) - - // existing ref - ref, err = ParseReference(fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost)) - suite.Nil(err) - err = suite.RegistryClient.RemoveChart(ref) - suite.Nil(err) -} - -func (suite *RegistryClientTestSuite) Test_7_Logout() { - err := suite.RegistryClient.Logout("this-host-aint-real:5000") - suite.NotNil(err, "error logging out of registry that has no entry") - - err = suite.RegistryClient.Logout(suite.DockerRegistryHost) - suite.Nil(err, "no error logging out of registry") -} - -func (suite *RegistryClientTestSuite) Test_8_ManInTheMiddle() { - ref, err := ParseReference(fmt.Sprintf("%s/testrepo/supposedlysafechart:9.9.9", suite.CompromisedRegistryHost)) - suite.Nil(err) - - // returns content that does not match the expected digest - _, err = suite.RegistryClient.PullChart(ref) - suite.NotNil(err) - suite.True(errdefs.IsFailedPrecondition(err)) -} - -func TestRegistryClientTestSuite(t *testing.T) { - suite.Run(t, new(RegistryClientTestSuite)) -} - -func initCompromisedRegistryTestServer() string { - s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if strings.Contains(r.URL.Path, "manifests") { - w.Header().Set("Content-Type", "application/vnd.oci.image.manifest.v1+json") - w.WriteHeader(200) - - // layers[0] is the blob []byte("a") - w.Write([]byte( - `{ "schemaVersion": 2, "config": { - "mediaType": "application/vnd.cncf.helm.config.v1+json", - "digest": "sha256:a705ee2789ab50a5ba20930f246dbd5cc01ff9712825bb98f57ee8414377f133", - "size": 181 - }, - "layers": [ - { - "mediaType": "application/tar+gzip", - "digest": "sha256:ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb", - "size": 1 - } - ] -}`)) - } else if r.URL.Path == "/v2/testrepo/supposedlysafechart/blobs/sha256:a705ee2789ab50a5ba20930f246dbd5cc01ff9712825bb98f57ee8414377f133" { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(200) - w.Write([]byte("{\"name\":\"mychart\",\"version\":\"0.1.0\",\"description\":\"A Helm chart for Kubernetes\\n" + - "an 'application' or a 'library' chart.\",\"apiVersion\":\"v2\",\"appVersion\":\"1.16.0\",\"type\":" + - "\"application\"}")) - } else if r.URL.Path == "/v2/testrepo/supposedlysafechart/blobs/sha256:ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb" { - w.Header().Set("Content-Type", "application/tar+gzip") - w.WriteHeader(200) - w.Write([]byte("b")) - } else { - w.WriteHeader(500) - } - })) - - u, _ := url.Parse(s.URL) - return fmt.Sprintf("localhost:%s", u.Port()) -} diff --git a/internal/experimental/registry/reference.go b/internal/experimental/registry/reference.go deleted file mode 100644 index f0e91d4ba..000000000 --- a/internal/experimental/registry/reference.go +++ /dev/null @@ -1,146 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package registry // import "helm.sh/helm/v3/internal/experimental/registry" - -import ( - "errors" - "fmt" - "net/url" - "regexp" - "strconv" - "strings" -) - -var ( - validPortRegEx = regexp.MustCompile(`^([1-9]\d{0,3}|0|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$`) // adapted from https://stackoverflow.com/a/12968117 - // TODO: Currently we don't support digests, so we are only splitting on the - // colon. However, when we add support for digests, we'll need to use the - // regexp anyway to split on both colons and @, so leaving it like this for - // now - referenceDelimiter = regexp.MustCompile(`[:]`) - errEmptyRepo = errors.New("parsed repo was empty") - errTooManyColons = errors.New("ref may only contain a single colon character (:) unless specifying a port number") -) - -type ( - // Reference defines the main components of a reference specification - Reference struct { - Tag string - Repo string - } -) - -// ParseReference converts a string to a Reference -func ParseReference(s string) (*Reference, error) { - if s == "" { - return nil, errEmptyRepo - } - // Split the components of the string on the colon or @, if it is more than 3, - // immediately return an error. Other validation will be performed later in - // the function - splitComponents := fixSplitComponents(referenceDelimiter.Split(s, -1)) - if len(splitComponents) > 3 { - return nil, errTooManyColons - } - - var ref *Reference - switch len(splitComponents) { - case 1: - ref = &Reference{Repo: splitComponents[0]} - case 2: - ref = &Reference{Repo: splitComponents[0], Tag: splitComponents[1]} - case 3: - ref = &Reference{Repo: strings.Join(splitComponents[:2], ":"), Tag: splitComponents[2]} - } - - // ensure the reference is valid - err := ref.validate() - if err != nil { - return nil, err - } - - return ref, nil -} - -// FullName the full name of a reference (repo:tag) -func (ref *Reference) FullName() string { - if ref.Tag == "" { - return ref.Repo - } - return fmt.Sprintf("%s:%s", ref.Repo, ref.Tag) -} - -// validate makes sure the ref meets our criteria -func (ref *Reference) validate() error { - - err := ref.validateRepo() - if err != nil { - return err - } - return ref.validateNumColons() -} - -// validateRepo checks that the Repo field is non-empty -func (ref *Reference) validateRepo() error { - if ref.Repo == "" { - return errEmptyRepo - } - // Makes sure the repo results in a parsable URL (similar to what is done - // with containerd reference parsing) - _, err := url.Parse("//" + ref.Repo) - return err -} - -// validateNumColons ensures the ref only contains a single colon character (:) -// (or potentially two, there might be a port number specified i.e. :5000) -func (ref *Reference) validateNumColons() error { - if strings.Contains(ref.Tag, ":") { - return errTooManyColons - } - parts := strings.Split(ref.Repo, ":") - lastIndex := len(parts) - 1 - if 1 < lastIndex { - return errTooManyColons - } - if 0 < lastIndex { - port := strings.Split(parts[lastIndex], "/")[0] - if !isValidPort(port) { - return errTooManyColons - } - } - return nil -} - -// isValidPort returns whether or not a string looks like a valid port -func isValidPort(s string) bool { - return validPortRegEx.MatchString(s) -} - -// fixSplitComponents this will modify reference parts based on presence of port -// Example: {localhost, 5000/x/y/z, 0.1.0} => {localhost:5000/x/y/z, 0.1.0} -func fixSplitComponents(c []string) []string { - if len(c) <= 1 { - return c - } - possiblePortParts := strings.Split(c[1], "/") - if _, err := strconv.Atoi(possiblePortParts[0]); err == nil { - components := []string{strings.Join(c[:2], ":")} - components = append(components, c[2:]...) - return components - } - return c -} diff --git a/internal/experimental/registry/reference_test.go b/internal/experimental/registry/reference_test.go deleted file mode 100644 index aae03ad99..000000000 --- a/internal/experimental/registry/reference_test.go +++ /dev/null @@ -1,126 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package registry - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestParseReference(t *testing.T) { - is := assert.New(t) - - // bad refs - s := "" - _, err := ParseReference(s) - is.Error(err, "empty ref") - - s = "my:bad:ref" - _, err = ParseReference(s) - is.Error(err, "ref contains too many colons (2)") - - s = "my:really:bad:ref" - _, err = ParseReference(s) - is.Error(err, "ref contains too many colons (3)") - - // good refs - s = "mychart" - ref, err := ParseReference(s) - is.NoError(err) - is.Equal("mychart", ref.Repo) - is.Equal("", ref.Tag) - is.Equal("mychart", ref.FullName()) - - s = "mychart:1.5.0" - ref, err = ParseReference(s) - is.NoError(err) - is.Equal("mychart", ref.Repo) - is.Equal("1.5.0", ref.Tag) - is.Equal("mychart:1.5.0", ref.FullName()) - - s = "myrepo/mychart" - ref, err = ParseReference(s) - is.NoError(err) - is.Equal("myrepo/mychart", ref.Repo) - is.Equal("", ref.Tag) - is.Equal("myrepo/mychart", ref.FullName()) - - s = "myrepo/mychart:1.5.0" - ref, err = ParseReference(s) - is.NoError(err) - is.Equal("myrepo/mychart", ref.Repo) - is.Equal("1.5.0", ref.Tag) - is.Equal("myrepo/mychart:1.5.0", ref.FullName()) - - s = "mychart:5001:1.5.0" - ref, err = ParseReference(s) - is.NoError(err) - is.Equal("mychart:5001", ref.Repo) - is.Equal("1.5.0", ref.Tag) - is.Equal("mychart:5001:1.5.0", ref.FullName()) - - s = "myrepo:5001/mychart:1.5.0" - ref, err = ParseReference(s) - is.NoError(err) - is.Equal("myrepo:5001/mychart", ref.Repo) - is.Equal("1.5.0", ref.Tag) - is.Equal("myrepo:5001/mychart:1.5.0", ref.FullName()) - - s = "127.0.0.1:5001/mychart:1.5.0" - ref, err = ParseReference(s) - is.NoError(err) - is.Equal("127.0.0.1:5001/mychart", ref.Repo) - is.Equal("1.5.0", ref.Tag) - is.Equal("127.0.0.1:5001/mychart:1.5.0", ref.FullName()) - - s = "localhost:5000/mychart:latest" - ref, err = ParseReference(s) - is.NoError(err) - is.Equal("localhost:5000/mychart", ref.Repo) - is.Equal("latest", ref.Tag) - is.Equal("localhost:5000/mychart:latest", ref.FullName()) - - s = "my.host.com/my/nested/repo:1.2.3" - ref, err = ParseReference(s) - is.NoError(err) - is.Equal("my.host.com/my/nested/repo", ref.Repo) - is.Equal("1.2.3", ref.Tag) - is.Equal("my.host.com/my/nested/repo:1.2.3", ref.FullName()) - - s = "localhost:5000/x/y/z" - ref, err = ParseReference(s) - is.NoError(err) - is.Equal("localhost:5000/x/y/z", ref.Repo) - is.Equal("", ref.Tag) - is.Equal("localhost:5000/x/y/z", ref.FullName()) - - s = "localhost:5000/x/y/z:123" - ref, err = ParseReference(s) - is.NoError(err) - is.Equal("localhost:5000/x/y/z", ref.Repo) - is.Equal("123", ref.Tag) - is.Equal("localhost:5000/x/y/z:123", ref.FullName()) - - s = "localhost:5000/x/y/z:123:x" - _, err = ParseReference(s) - is.Error(err, "ref contains too many colons (3)") - - s = "localhost:5000/x/y/z:123:x:y" - _, err = ParseReference(s) - is.Error(err, "ref contains too many colons (4)") -} diff --git a/internal/experimental/registry/registry_client.go b/internal/experimental/registry/registry_client.go new file mode 100644 index 000000000..e787d5652 --- /dev/null +++ b/internal/experimental/registry/registry_client.go @@ -0,0 +1,78 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package registry // import "helm.sh/helm/v3/internal/experimental/registry" + +import ( + "fmt" + "io" + "io/ioutil" + "net/http" + + "github.com/containerd/containerd/remotes" + "github.com/oras-project/oras-go/pkg/auth" + dockerauth "github.com/oras-project/oras-go/pkg/auth/docker" + + "helm.sh/helm/v3/internal/version" + "helm.sh/helm/v3/pkg/helmpath" +) + +var ( + userAgent = fmt.Sprintf("helm/%s", version.GetVersion()) +) + +type ( + // Client works with OCI-compliant registries + Client struct { + debug bool + // path to repository config file e.g. ~/.docker/config.json + credentialsFile string + out io.Writer + authorizer auth.Client + resolver remotes.Resolver + } +) + +// NewClient returns a new registry client with config +func NewClient(options ...ClientOption) (*Client, error) { + client := &Client{ + out: ioutil.Discard, + } + for _, option := range options { + option(client) + } + if client.credentialsFile == "" { + client.credentialsFile = helmpath.CachePath("registry", CredentialsFileBasename) + } + if client.authorizer == nil { + authClient, err := dockerauth.NewClient(client.credentialsFile) + if err != nil { + return nil, err + } + client.authorizer = authClient + } + if client.resolver == nil { + headers := http.Header{} + headers.Set("User-Agent", userAgent) + opts := []auth.ResolverOption{auth.WithResolverHeaders(headers)} + resolver, err := client.authorizer.ResolverWithOpts(opts...) + if err != nil { + return nil, err + } + client.resolver = resolver + } + return client, nil +} diff --git a/internal/experimental/registry/client_opts.go b/internal/experimental/registry/registry_client_options.go similarity index 58% rename from internal/experimental/registry/client_opts.go rename to internal/experimental/registry/registry_client_options.go index 266cf3f6f..1298f2998 100644 --- a/internal/experimental/registry/client_opts.go +++ b/internal/experimental/registry/registry_client_options.go @@ -40,37 +40,9 @@ func ClientOptWriter(out io.Writer) ClientOption { } } -// ClientOptResolver returns a function that sets the resolver setting on client options set -func ClientOptResolver(resolver *Resolver) ClientOption { - return func(client *Client) { - client.resolver = resolver - } -} - -// ClientOptAuthorizer returns a function that sets the authorizer setting on client options set -func ClientOptAuthorizer(authorizer *Authorizer) ClientOption { - return func(client *Client) { - client.authorizer = authorizer - } -} - -// ClientOptCache returns a function that sets the cache setting on a client options set -func ClientOptCache(cache *Cache) ClientOption { - return func(client *Client) { - client.cache = cache - } -} - -// ClientOptCredentialsFile returns a function that sets the cache setting on a client options set +// ClientOptCredentialsFile returns a function that sets the credentialsFile setting on a client options set func ClientOptCredentialsFile(credentialsFile string) ClientOption { return func(client *Client) { client.credentialsFile = credentialsFile } } - -// ClientOptColumnWidth returns a function that sets the column width on a client options set -func ClientOptColumnWidth(columnWidth uint) ClientOption { - return func(client *Client) { - client.columnWidth = columnWidth - } -} diff --git a/internal/experimental/registry/registry_constants.go b/internal/experimental/registry/registry_constants.go new file mode 100644 index 000000000..5c16f2f24 --- /dev/null +++ b/internal/experimental/registry/registry_constants.go @@ -0,0 +1,31 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package registry // import "helm.sh/helm/v3/internal/experimental/registry" + +const ( + // CredentialsFileBasename is the filename for auth credentials file + CredentialsFileBasename = "config.json" + + // ConfigMediaType is the reserved media type for the Helm chart manifest config + ConfigMediaType = "application/vnd.cncf.helm.config.v1+json" + + // ChartLayerMediaType is the reserved media type for Helm chart package content + ChartLayerMediaType = "application/vnd.cncf.helm.chart.content.v1.tar+gzip" + + // ProvLayerMediaType is the reserved media type for Helm chart provenance files + ProvLayerMediaType = "application/vnd.cncf.helm.chart.provenance.v1.prov" +) diff --git a/internal/experimental/registry/registry_op_login.go b/internal/experimental/registry/registry_op_login.go new file mode 100644 index 000000000..8d2aa183a --- /dev/null +++ b/internal/experimental/registry/registry_op_login.go @@ -0,0 +1,50 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package registry // import "helm.sh/helm/v3/internal/experimental/registry" + +import ( + "fmt" + + "github.com/oras-project/oras-go/pkg/auth" +) + +// Login logs into a registry +func (c *Client) Login(host string, options ...LoginOption) (*LoginResult, error) { + operation := &loginOperation{} + for _, option := range options { + option(operation) + } + authorizerLoginOpts := []auth.LoginOption{ + auth.WithLoginContext(ctx(c.out, c.debug)), + auth.WithLoginHostname(host), + auth.WithLoginUsername(operation.username), + auth.WithLoginSecret(operation.password), + auth.WithLoginUserAgent(userAgent), + } + if operation.insecure { + authorizerLoginOpts = append(authorizerLoginOpts, auth.WithLoginInsecure()) + } + err := c.authorizer.LoginWithOpts(authorizerLoginOpts...) + if err != nil { + return nil, err + } + result := &LoginResult{ + Host: host, + } + fmt.Fprintln(c.out, "Login Succeeded") + return result, nil +} diff --git a/internal/experimental/registry/registry_op_login_options.go b/internal/experimental/registry/registry_op_login_options.go new file mode 100644 index 000000000..fff107a91 --- /dev/null +++ b/internal/experimental/registry/registry_op_login_options.go @@ -0,0 +1,43 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package registry // import "helm.sh/helm/v3/internal/experimental/registry" + +type ( + // LoginOption allows specifying various settings on login + LoginOption func(*loginOperation) + + loginOperation struct { + username string + password string + insecure bool + } +) + +// LoginOptBasicAuth returns a function that sets the username/password settings on login +func LoginOptBasicAuth(username string, password string) LoginOption { + return func(operation *loginOperation) { + operation.username = username + operation.password = password + } +} + +// LoginOptInsecure returns a function that sets the insecure setting on login +func LoginOptInsecure(insecure bool) LoginOption { + return func(operation *loginOperation) { + operation.insecure = insecure + } +} diff --git a/internal/experimental/registry/authorizer.go b/internal/experimental/registry/registry_op_login_result.go similarity index 83% rename from internal/experimental/registry/authorizer.go rename to internal/experimental/registry/registry_op_login_result.go index 918a999ba..225bf73cc 100644 --- a/internal/experimental/registry/authorizer.go +++ b/internal/experimental/registry/registry_op_login_result.go @@ -16,13 +16,9 @@ limitations under the License. package registry // import "helm.sh/helm/v3/internal/experimental/registry" -import ( - "github.com/deislabs/oras/pkg/auth" -) - type ( - // Authorizer handles registry auth operations - Authorizer struct { - auth.Client + // LoginResult is the result returned upon successful login. + LoginResult struct { + Host string `json:"host"` } ) diff --git a/internal/experimental/registry/constants.go b/internal/experimental/registry/registry_op_logout.go similarity index 55% rename from internal/experimental/registry/constants.go rename to internal/experimental/registry/registry_op_logout.go index dafb3c9e5..0e487f1e8 100644 --- a/internal/experimental/registry/constants.go +++ b/internal/experimental/registry/registry_op_logout.go @@ -16,18 +16,23 @@ limitations under the License. package registry // import "helm.sh/helm/v3/internal/experimental/registry" -const ( - // HelmChartConfigMediaType is the reserved media type for the Helm chart manifest config - HelmChartConfigMediaType = "application/vnd.cncf.helm.config.v1+json" - - // HelmChartContentLayerMediaType is the reserved media type for Helm chart package content - HelmChartContentLayerMediaType = "application/tar+gzip" +import ( + "fmt" ) -// KnownMediaTypes returns a list of layer mediaTypes that the Helm client knows about -func KnownMediaTypes() []string { - return []string{ - HelmChartConfigMediaType, - HelmChartContentLayerMediaType, +// Logout logs out of a registry +func (c *Client) Logout(host string, opts ...LogoutOption) (*LogoutResult, error) { + operation := &logoutOperation{} + for _, opt := range opts { + opt(operation) + } + err := c.authorizer.Logout(ctx(c.out, c.debug), host) + if err != nil { + return nil, err + } + result := &LogoutResult{ + Host: host, } + fmt.Fprintf(c.out, "Removing login credentials for %s\n", result.Host) + return result, nil } diff --git a/internal/experimental/registry/constants_test.go b/internal/experimental/registry/registry_op_logout_options.go similarity index 66% rename from internal/experimental/registry/constants_test.go rename to internal/experimental/registry/registry_op_logout_options.go index 9f078e632..13e2f04fe 100644 --- a/internal/experimental/registry/constants_test.go +++ b/internal/experimental/registry/registry_op_logout_options.go @@ -14,16 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -package registry +package registry // import "helm.sh/helm/v3/internal/experimental/registry" -import ( - "testing" +type ( + // LogoutOption allows specifying various settings on logout + LogoutOption func(*logoutOperation) - "github.com/stretchr/testify/assert" + logoutOperation struct{} ) - -func TestConstants(t *testing.T) { - knownMediaTypes := KnownMediaTypes() - assert.Contains(t, knownMediaTypes, HelmChartConfigMediaType) - assert.Contains(t, knownMediaTypes, HelmChartContentLayerMediaType) -} diff --git a/internal/experimental/registry/resolver.go b/internal/experimental/registry/registry_op_logout_result.go similarity index 81% rename from internal/experimental/registry/resolver.go rename to internal/experimental/registry/registry_op_logout_result.go index ff8a82633..8bd2a3695 100644 --- a/internal/experimental/registry/resolver.go +++ b/internal/experimental/registry/registry_op_logout_result.go @@ -16,13 +16,9 @@ limitations under the License. package registry // import "helm.sh/helm/v3/internal/experimental/registry" -import ( - "github.com/containerd/containerd/remotes" -) - type ( - // Resolver provides remotes based on a locator - Resolver struct { - remotes.Resolver + // LogoutResult is the result returned upon successful logout. + LogoutResult struct { + Host string `json:"host"` } ) diff --git a/internal/experimental/registry/registry_op_pull.go b/internal/experimental/registry/registry_op_pull.go new file mode 100644 index 000000000..f1f9d9254 --- /dev/null +++ b/internal/experimental/registry/registry_op_pull.go @@ -0,0 +1,164 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package registry // import "helm.sh/helm/v3/internal/experimental/registry" + +import ( + "encoding/json" + "fmt" + + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/oras-project/oras-go/pkg/content" + "github.com/oras-project/oras-go/pkg/oras" + "github.com/pkg/errors" + + "helm.sh/helm/v3/pkg/chart" +) + +// Pull downloads a chart from a registry +func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) { + operation := &pullOperation{ + withChart: true, // By default, always download the chart layer + } + for _, option := range options { + option(operation) + } + if !operation.withChart && !operation.withProv { + return nil, errors.New( + "must specify at least one layer to pull (chart/prov)") + } + store := content.NewMemoryStore() + allowedMediaTypes := []string{ + ConfigMediaType, + } + minNumDescriptors := 1 // 1 for the config + if operation.withChart { + minNumDescriptors++ + allowedMediaTypes = append(allowedMediaTypes, ChartLayerMediaType) + } + if operation.withProv { + if !operation.ignoreMissingProv { + minNumDescriptors++ + } + allowedMediaTypes = append(allowedMediaTypes, ProvLayerMediaType) + } + manifest, descriptors, err := oras.Pull(ctx(c.out, c.debug), c.resolver, ref, store, + oras.WithPullEmptyNameAllowed(), + oras.WithAllowedMediaTypes(allowedMediaTypes)) + if err != nil { + return nil, err + } + numDescriptors := len(descriptors) + if numDescriptors < minNumDescriptors { + return nil, errors.New( + fmt.Sprintf("manifest does not contain minimum number of descriptors (%d), descriptors found: %d", + minNumDescriptors, numDescriptors)) + } + var configDescriptor *ocispec.Descriptor + var chartDescriptor *ocispec.Descriptor + var provDescriptor *ocispec.Descriptor + for _, descriptor := range descriptors { + d := descriptor + switch d.MediaType { + case ConfigMediaType: + configDescriptor = &d + case ChartLayerMediaType: + chartDescriptor = &d + case ProvLayerMediaType: + provDescriptor = &d + } + } + if configDescriptor == nil { + return nil, errors.New( + fmt.Sprintf("could not load config with mediatype %s", ConfigMediaType)) + } + if operation.withChart && chartDescriptor == nil { + return nil, errors.New( + fmt.Sprintf("manifest does not contain a layer with mediatype %s", + ChartLayerMediaType)) + } + var provMissing bool + if operation.withProv && provDescriptor == nil { + if operation.ignoreMissingProv { + provMissing = true + } else { + return nil, errors.New( + fmt.Sprintf("manifest does not contain a layer with mediatype %s", + ProvLayerMediaType)) + } + } + _, manifestData, ok := store.Get(manifest) + if !ok { + return nil, errors.Errorf("Unable to retrieve blob with digest %s", manifest.Digest) + } + _, configData, ok := store.Get(*configDescriptor) + if !ok { + return nil, errors.Errorf("Unable to retrieve blob with digest %s", configDescriptor.Digest) + } + var meta *chart.Metadata + err = json.Unmarshal(configData, &meta) + if err != nil { + return nil, err + } + var chartData []byte + if operation.withChart { + var ok bool + _, chartData, ok = store.Get(*chartDescriptor) + if !ok { + return nil, errors.Errorf("Unable to retrieve blob with digest %s", chartDescriptor.Digest) + } + } + var provData []byte + if operation.withProv && !provMissing { + var ok bool + _, provData, ok = store.Get(*provDescriptor) + if !ok { + return nil, errors.Errorf("Unable to retrieve blob with digest %s", provDescriptor.Digest) + } + } + result := &PullResult{ + Manifest: &descriptorPullSummary{ + Data: manifestData, + Digest: manifest.Digest.String(), + Size: manifest.Size, + }, + Config: &descriptorPullSummary{ + Data: configData, + Digest: configDescriptor.Digest.String(), + Size: configDescriptor.Size, + }, + Chart: &descriptorPullSummaryWithMeta{ + Meta: meta, + }, + Prov: &descriptorPullSummary{}, // prevent nil references + Ref: ref, + } + if chartData != nil { + result.Chart.Data = chartData + result.Chart.Digest = chartDescriptor.Digest.String() + result.Chart.Size = chartDescriptor.Size + } + if provData != nil { + result.Prov = &descriptorPullSummary{ + Data: provData, + Digest: provDescriptor.Digest.String(), + Size: provDescriptor.Size, + } + } + fmt.Fprintf(c.out, "Pulled: %s\n", result.Ref) + fmt.Fprintf(c.out, "Digest: %s\n", result.Manifest.Digest) + return result, nil +} diff --git a/internal/experimental/registry/registry_op_pull_options.go b/internal/experimental/registry/registry_op_pull_options.go new file mode 100644 index 000000000..372dbb7b1 --- /dev/null +++ b/internal/experimental/registry/registry_op_pull_options.go @@ -0,0 +1,49 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package registry // import "helm.sh/helm/v3/internal/experimental/registry" + +type ( + // PullOption allows specifying various settings on pull + PullOption func(*pullOperation) + + pullOperation struct { + withChart bool + withProv bool + ignoreMissingProv bool + } +) + +// PullOptWithChart returns a function that sets the withChart setting on pull +func PullOptWithChart(withChart bool) PullOption { + return func(operation *pullOperation) { + operation.withChart = withChart + } +} + +// PullOptWithProv returns a function that sets the withProv setting on pull +func PullOptWithProv(withProv bool) PullOption { + return func(operation *pullOperation) { + operation.withProv = withProv + } +} + +// PullOptIgnoreMissingProv returns a function that sets the ignoreMissingProv setting on pull +func PullOptIgnoreMissingProv(ignoreMissingProv bool) PullOption { + return func(operation *pullOperation) { + operation.ignoreMissingProv = ignoreMissingProv + } +} diff --git a/internal/experimental/registry/registry_op_pull_result.go b/internal/experimental/registry/registry_op_pull_result.go new file mode 100644 index 000000000..d3aab03de --- /dev/null +++ b/internal/experimental/registry/registry_op_pull_result.go @@ -0,0 +1,43 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package registry // import "helm.sh/helm/v3/internal/experimental/registry" + +import ( + "helm.sh/helm/v3/pkg/chart" +) + +type ( + // PullResult is the result returned upon successful pull. + PullResult struct { + Manifest *descriptorPullSummary `json:"manifest"` + Config *descriptorPullSummary `json:"config"` + Chart *descriptorPullSummaryWithMeta `json:"chart"` + Prov *descriptorPullSummary `json:"prov"` + Ref string `json:"ref"` + } + + descriptorPullSummary struct { + Data []byte `json:"-"` + Digest string `json:"digest"` + Size int64 `json:"size"` + } + + descriptorPullSummaryWithMeta struct { + descriptorPullSummary + Meta *chart.Metadata `json:"meta"` + } +) diff --git a/internal/experimental/registry/registry_op_push.go b/internal/experimental/registry/registry_op_push.go new file mode 100644 index 000000000..fcf999b13 --- /dev/null +++ b/internal/experimental/registry/registry_op_push.go @@ -0,0 +1,93 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package registry // import "helm.sh/helm/v3/internal/experimental/registry" + +import ( + "encoding/json" + "errors" + "fmt" + "strings" + + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/oras-project/oras-go/pkg/content" + "github.com/oras-project/oras-go/pkg/oras" +) + +// Push uploads a chart to a registry. +func (c *Client) Push(data []byte, ref string, options ...PushOption) (*PushResult, error) { + operation := &pushOperation{ + strictMode: true, // By default, enable strict mode + } + for _, option := range options { + option(operation) + } + meta, err := extractChartMeta(data) + if err != nil { + return nil, err + } + if operation.strictMode { + if !strings.HasSuffix(ref, fmt.Sprintf("/%s:%s", meta.Name, meta.Version)) { + return nil, errors.New( + "strict mode enabled, ref basename and tag must match the chart name and version") + } + } + store := content.NewMemoryStore() + chartDescriptor := store.Add("", ChartLayerMediaType, data) + configData, err := json.Marshal(meta) + if err != nil { + return nil, err + } + configDescriptor := store.Add("", ConfigMediaType, configData) + descriptors := []ocispec.Descriptor{chartDescriptor} + var provDescriptor ocispec.Descriptor + if operation.provData != nil { + provDescriptor = store.Add("", ProvLayerMediaType, operation.provData) + descriptors = append(descriptors, provDescriptor) + } + manifest, err := oras.Push(ctx(c.out, c.debug), c.resolver, ref, store, descriptors, + oras.WithConfig(configDescriptor), oras.WithNameValidation(nil)) + if err != nil { + return nil, err + } + chartSummary := &descriptorPushSummaryWithMeta{ + Meta: meta, + } + chartSummary.Digest = chartDescriptor.Digest.String() + chartSummary.Size = chartDescriptor.Size + result := &PushResult{ + Manifest: &descriptorPushSummary{ + Digest: manifest.Digest.String(), + Size: manifest.Size, + }, + Config: &descriptorPushSummary{ + Digest: configDescriptor.Digest.String(), + Size: configDescriptor.Size, + }, + Chart: chartSummary, + Prov: &descriptorPushSummary{}, // prevent nil references + Ref: ref, + } + if operation.provData != nil { + result.Prov = &descriptorPushSummary{ + Digest: provDescriptor.Digest.String(), + Size: provDescriptor.Size, + } + } + fmt.Fprintf(c.out, "Pushed: %s\n", result.Ref) + fmt.Fprintf(c.out, "Digest: %s\n", result.Manifest.Digest) + return result, err +} diff --git a/internal/experimental/registry/registry_op_push_options.go b/internal/experimental/registry/registry_op_push_options.go new file mode 100644 index 000000000..6b54fd0d7 --- /dev/null +++ b/internal/experimental/registry/registry_op_push_options.go @@ -0,0 +1,41 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package registry // import "helm.sh/helm/v3/internal/experimental/registry" + +type ( + // PushOption allows specifying various settings on push + PushOption func(*pushOperation) + + pushOperation struct { + provData []byte + strictMode bool + } +) + +// PushOptProvData returns a function that sets the prov bytes setting on push +func PushOptProvData(provData []byte) PushOption { + return func(operation *pushOperation) { + operation.provData = provData + } +} + +// PushOptStrictMode returns a function that sets the strictMode setting on push +func PushOptStrictMode(strictMode bool) PushOption { + return func(operation *pushOperation) { + operation.strictMode = strictMode + } +} diff --git a/internal/experimental/registry/registry_op_push_result.go b/internal/experimental/registry/registry_op_push_result.go new file mode 100644 index 000000000..3541bf414 --- /dev/null +++ b/internal/experimental/registry/registry_op_push_result.go @@ -0,0 +1,42 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package registry // import "helm.sh/helm/v3/internal/experimental/registry" + +import ( + "helm.sh/helm/v3/pkg/chart" +) + +type ( + // PushResult is the result returned upon successful push. + PushResult struct { + Manifest *descriptorPushSummary `json:"manifest"` + Config *descriptorPushSummary `json:"config"` + Chart *descriptorPushSummaryWithMeta `json:"chart"` + Prov *descriptorPushSummary `json:"prov"` + Ref string `json:"ref"` + } + + descriptorPushSummary struct { + Digest string `json:"digest"` + Size int64 `json:"size"` + } + + descriptorPushSummaryWithMeta struct { + descriptorPushSummary + Meta *chart.Metadata `json:"meta"` + } +) diff --git a/internal/experimental/registry/registry_test.go b/internal/experimental/registry/registry_test.go new file mode 100644 index 000000000..c402731f9 --- /dev/null +++ b/internal/experimental/registry/registry_test.go @@ -0,0 +1,359 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package registry + +import ( + "bytes" + "context" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/http/httptest" + "net/url" + "os" + "path/filepath" + "strings" + "testing" + "time" + + "github.com/containerd/containerd/errdefs" + "github.com/docker/distribution/configuration" + "github.com/docker/distribution/registry" + _ "github.com/docker/distribution/registry/auth/htpasswd" + _ "github.com/docker/distribution/registry/storage/driver/inmemory" + "github.com/phayes/freeport" + "github.com/stretchr/testify/suite" + "golang.org/x/crypto/bcrypt" +) + +var ( + testWorkspaceDir = "helm-registry-test" + testHtpasswdFileBasename = "authtest.htpasswd" + testUsername = "myuser" + testPassword = "mypass" +) + +type RegistryClientTestSuite struct { + suite.Suite + Out io.Writer + DockerRegistryHost string + CompromisedRegistryHost string + WorkspaceDir string + RegistryClient *Client +} + +func (suite *RegistryClientTestSuite) SetupSuite() { + suite.WorkspaceDir = testWorkspaceDir + os.RemoveAll(suite.WorkspaceDir) + os.Mkdir(suite.WorkspaceDir, 0700) + + var out bytes.Buffer + suite.Out = &out + credentialsFile := filepath.Join(suite.WorkspaceDir, CredentialsFileBasename) + + // init test client + var err error + suite.RegistryClient, err = NewClient( + ClientOptDebug(true), + ClientOptWriter(suite.Out), + ClientOptCredentialsFile(credentialsFile), + ) + suite.Nil(err, "no error creating registry client") + + // create htpasswd file (w BCrypt, which is required) + pwBytes, err := bcrypt.GenerateFromPassword([]byte(testPassword), bcrypt.DefaultCost) + suite.Nil(err, "no error generating bcrypt password for test htpasswd file") + htpasswdPath := filepath.Join(suite.WorkspaceDir, testHtpasswdFileBasename) + err = ioutil.WriteFile(htpasswdPath, []byte(fmt.Sprintf("%s:%s\n", testUsername, string(pwBytes))), 0644) + suite.Nil(err, "no error creating test htpasswd file") + + // Registry config + config := &configuration.Configuration{} + port, err := freeport.GetFreePort() + suite.Nil(err, "no error finding free port for test registry") + suite.DockerRegistryHost = fmt.Sprintf("localhost:%d", port) + config.HTTP.Addr = fmt.Sprintf(":%d", port) + config.HTTP.DrainTimeout = time.Duration(10) * time.Second + config.Storage = map[string]configuration.Parameters{"inmemory": map[string]interface{}{}} + config.Auth = configuration.Auth{ + "htpasswd": configuration.Parameters{ + "realm": "localhost", + "path": htpasswdPath, + }, + } + dockerRegistry, err := registry.NewRegistry(context.Background(), config) + suite.Nil(err, "no error creating test registry") + + suite.CompromisedRegistryHost = initCompromisedRegistryTestServer() + + // Start Docker registry + go dockerRegistry.ListenAndServe() +} + +func (suite *RegistryClientTestSuite) TearDownSuite() { + os.RemoveAll(suite.WorkspaceDir) +} + +func (suite *RegistryClientTestSuite) Test_0_Login() { + _, err := suite.RegistryClient.Login(suite.DockerRegistryHost, + LoginOptBasicAuth("badverybad", "ohsobad"), + LoginOptInsecure(false)) + suite.NotNil(err, "error logging into registry with bad credentials") + + _, err = suite.RegistryClient.Login(suite.DockerRegistryHost, + LoginOptBasicAuth("badverybad", "ohsobad"), + LoginOptInsecure(true)) + suite.NotNil(err, "error logging into registry with bad credentials, insecure mode") + + result, err := suite.RegistryClient.Login(suite.DockerRegistryHost, + LoginOptBasicAuth(testUsername, testPassword), + LoginOptInsecure(false)) + suite.Nil(err, "no error logging into registry with good credentials") + suite.Equal(suite.DockerRegistryHost, result.Host, "result.Host is as expected") + + _, err = suite.RegistryClient.Login(suite.DockerRegistryHost, + LoginOptBasicAuth(testUsername, testPassword), + LoginOptInsecure(true)) + suite.Nil(err, "no error logging into registry with good credentials, insecure mode") + suite.Equal(suite.DockerRegistryHost, result.Host, "result.Host is as expected") +} + +func (suite *RegistryClientTestSuite) Test_1_Push() { + // Bad bytes + ref := fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost) + _, err := suite.RegistryClient.Push([]byte("hello"), ref) + suite.NotNil(err, "error pushing non-chart bytes") + + // Load a test chart + chartData, err := ioutil.ReadFile("../../../pkg/repo/repotest/testdata/examplechart-0.1.0.tgz") + suite.Nil(err, "no error loading test chart") + meta, err := extractChartMeta(chartData) + suite.Nil(err, "no error extracting chart meta") + + // non-strict ref (chart name) + ref = fmt.Sprintf("%s/testrepo/boop:%s", suite.DockerRegistryHost, meta.Version) + _, err = suite.RegistryClient.Push(chartData, ref) + suite.NotNil(err, "error pushing non-strict ref (bad basename)") + + // non-strict ref (chart name), with strict mode disabled + _, err = suite.RegistryClient.Push(chartData, ref, PushOptStrictMode(false)) + suite.Nil(err, "no error pushing non-strict ref (bad basename), with strict mode disabled") + + // non-strict ref (chart version) + ref = fmt.Sprintf("%s/testrepo/%s:latest", suite.DockerRegistryHost, meta.Name) + _, err = suite.RegistryClient.Push(chartData, ref) + suite.NotNil(err, "error pushing non-strict ref (bad tag)") + + // non-strict ref (chart version), with strict mode disabled + _, err = suite.RegistryClient.Push(chartData, ref, PushOptStrictMode(false)) + suite.Nil(err, "no error pushing non-strict ref (bad tag), with strict mode disabled") + + // basic push, good ref + chartData, err = ioutil.ReadFile("../../../pkg/downloader/testdata/local-subchart-0.1.0.tgz") + suite.Nil(err, "no error loading test chart") + meta, err = extractChartMeta(chartData) + suite.Nil(err, "no error extracting chart meta") + ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version) + _, err = suite.RegistryClient.Push(chartData, ref) + suite.Nil(err, "no error pushing good ref") + + _, err = suite.RegistryClient.Pull(ref) + suite.Nil(err, "no error pulling a simple chart") + + // Load another test chart + chartData, err = ioutil.ReadFile("../../../pkg/downloader/testdata/signtest-0.1.0.tgz") + suite.Nil(err, "no error loading test chart") + meta, err = extractChartMeta(chartData) + suite.Nil(err, "no error extracting chart meta") + + // Load prov file + provData, err := ioutil.ReadFile("../../../pkg/downloader/testdata/signtest-0.1.0.tgz.prov") + suite.Nil(err, "no error loading test prov") + + // push with prov + ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version) + result, err := suite.RegistryClient.Push(chartData, ref, PushOptProvData(provData)) + suite.Nil(err, "no error pushing good ref with prov") + + _, err = suite.RegistryClient.Pull(ref) + suite.Nil(err, "no error pulling a simple chart") + + // Validate the output + // Note: these digests/sizes etc may change if the test chart/prov files are modified, + // or if the format of the OCI manifest changes + suite.Equal(ref, result.Ref) + suite.Equal(meta.Name, result.Chart.Meta.Name) + suite.Equal(meta.Version, result.Chart.Meta.Version) + suite.Equal(int64(512), result.Manifest.Size) + suite.Equal(int64(99), result.Config.Size) + suite.Equal(int64(973), result.Chart.Size) + suite.Equal(int64(695), result.Prov.Size) + suite.Equal( + "sha256:c4fd4ca31f12f50a7f704bb1dfdf2e768b1e8bdeac3991b534b6bdb3f535aab1", + result.Manifest.Digest) + suite.Equal( + "sha256:8d17cb6bf6ccd8c29aace9a658495cbd5e2e87fc267876e86117c7db681c9580", + result.Config.Digest) + suite.Equal( + "sha256:e5ef611620fb97704d8751c16bab17fedb68883bfb0edc76f78a70e9173f9b55", + result.Chart.Digest) + suite.Equal( + "sha256:b0a02b7412f78ae93324d48df8fcc316d8482e5ad7827b5b238657a29a22f256", + result.Prov.Digest) +} + +func (suite *RegistryClientTestSuite) Test_2_Pull() { + // bad/missing ref + ref := fmt.Sprintf("%s/testrepo/no-existy:1.2.3", suite.DockerRegistryHost) + _, err := suite.RegistryClient.Pull(ref) + suite.NotNil(err, "error on bad/missing ref") + + // Load test chart (to build ref pushed in previous test) + chartData, err := ioutil.ReadFile("../../../pkg/downloader/testdata/local-subchart-0.1.0.tgz") + suite.Nil(err, "no error loading test chart") + meta, err := extractChartMeta(chartData) + suite.Nil(err, "no error extracting chart meta") + ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version) + + // Simple pull, chart only + _, err = suite.RegistryClient.Pull(ref) + suite.Nil(err, "no error pulling a simple chart") + + // Simple pull with prov (no prov uploaded) + _, err = suite.RegistryClient.Pull(ref, PullOptWithProv(true)) + suite.NotNil(err, "error pulling a chart with prov when no prov exists") + + // Simple pull with prov, ignoring missing prov + _, err = suite.RegistryClient.Pull(ref, + PullOptWithProv(true), + PullOptIgnoreMissingProv(true)) + suite.Nil(err, + "no error pulling a chart with prov when no prov exists, ignoring missing") + + // Load test chart (to build ref pushed in previous test) + chartData, err = ioutil.ReadFile("../../../pkg/downloader/testdata/signtest-0.1.0.tgz") + suite.Nil(err, "no error loading test chart") + meta, err = extractChartMeta(chartData) + suite.Nil(err, "no error extracting chart meta") + ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version) + + // Load prov file + provData, err := ioutil.ReadFile("../../../pkg/downloader/testdata/signtest-0.1.0.tgz.prov") + suite.Nil(err, "no error loading test prov") + + // no chart and no prov causes error + _, err = suite.RegistryClient.Pull(ref, + PullOptWithChart(false), + PullOptWithProv(false)) + suite.NotNil(err, "error on both no chart and no prov") + + // full pull with chart and prov + result, err := suite.RegistryClient.Pull(ref, PullOptWithProv(true)) + suite.Nil(err, "no error pulling a chart with prov") + + // Validate the output + // Note: these digests/sizes etc may change if the test chart/prov files are modified, + // or if the format of the OCI manifest changes + suite.Equal(ref, result.Ref) + suite.Equal(meta.Name, result.Chart.Meta.Name) + suite.Equal(meta.Version, result.Chart.Meta.Version) + suite.Equal(int64(512), result.Manifest.Size) + suite.Equal(int64(99), result.Config.Size) + suite.Equal(int64(973), result.Chart.Size) + suite.Equal(int64(695), result.Prov.Size) + suite.Equal( + "sha256:c4fd4ca31f12f50a7f704bb1dfdf2e768b1e8bdeac3991b534b6bdb3f535aab1", + result.Manifest.Digest) + suite.Equal( + "sha256:8d17cb6bf6ccd8c29aace9a658495cbd5e2e87fc267876e86117c7db681c9580", + result.Config.Digest) + suite.Equal( + "sha256:e5ef611620fb97704d8751c16bab17fedb68883bfb0edc76f78a70e9173f9b55", + result.Chart.Digest) + suite.Equal( + "sha256:b0a02b7412f78ae93324d48df8fcc316d8482e5ad7827b5b238657a29a22f256", + result.Prov.Digest) + suite.Equal("{\"schemaVersion\":2,\"config\":{\"mediaType\":\"application/vnd.cncf.helm.config.v1+json\",\"digest\":\"sha256:8d17cb6bf6ccd8c29aace9a658495cbd5e2e87fc267876e86117c7db681c9580\",\"size\":99},\"layers\":[{\"mediaType\":\"application/vnd.cncf.helm.chart.content.v1.tar+gzip\",\"digest\":\"sha256:e5ef611620fb97704d8751c16bab17fedb68883bfb0edc76f78a70e9173f9b55\",\"size\":973},{\"mediaType\":\"application/vnd.cncf.helm.chart.provenance.v1.prov\",\"digest\":\"sha256:b0a02b7412f78ae93324d48df8fcc316d8482e5ad7827b5b238657a29a22f256\",\"size\":695}]}", + string(result.Manifest.Data)) + suite.Equal("{\"name\":\"signtest\",\"version\":\"0.1.0\",\"description\":\"A Helm chart for Kubernetes\",\"apiVersion\":\"v1\"}", + string(result.Config.Data)) + suite.Equal(chartData, result.Chart.Data) + suite.Equal(provData, result.Prov.Data) +} + +func (suite *RegistryClientTestSuite) Test_3_Logout() { + _, err := suite.RegistryClient.Logout("this-host-aint-real:5000") + suite.NotNil(err, "error logging out of registry that has no entry") + + result, err := suite.RegistryClient.Logout(suite.DockerRegistryHost) + suite.Nil(err, "no error logging out of registry") + suite.Equal(suite.DockerRegistryHost, result.Host, "result.Host is as expected") +} + +func (suite *RegistryClientTestSuite) Test_4_ManInTheMiddle() { + ref := fmt.Sprintf("%s/testrepo/supposedlysafechart:9.9.9", suite.CompromisedRegistryHost) + + // returns content that does not match the expected digest + _, err := suite.RegistryClient.Pull(ref) + suite.NotNil(err) + suite.True(errdefs.IsFailedPrecondition(err)) +} + +func TestRegistryClientTestSuite(t *testing.T) { + suite.Run(t, new(RegistryClientTestSuite)) +} + +func initCompromisedRegistryTestServer() string { + s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if strings.Contains(r.URL.Path, "manifests") { + w.Header().Set("Content-Type", "application/vnd.oci.image.manifest.v1+json") + w.WriteHeader(200) + + // layers[0] is the blob []byte("a") + w.Write([]byte( + fmt.Sprintf(`{ "schemaVersion": 2, "config": { + "mediaType": "%s", + "digest": "sha256:a705ee2789ab50a5ba20930f246dbd5cc01ff9712825bb98f57ee8414377f133", + "size": 181 + }, + "layers": [ + { + "mediaType": "%s", + "digest": "sha256:ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb", + "size": 1 + } + ] +}`, ConfigMediaType, ChartLayerMediaType))) + } else if r.URL.Path == "/v2/testrepo/supposedlysafechart/blobs/sha256:a705ee2789ab50a5ba20930f246dbd5cc01ff9712825bb98f57ee8414377f133" { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + w.Write([]byte("{\"name\":\"mychart\",\"version\":\"0.1.0\",\"description\":\"A Helm chart for Kubernetes\\n" + + "an 'application' or a 'library' chart.\",\"apiVersion\":\"v2\",\"appVersion\":\"1.16.0\",\"type\":" + + "\"application\"}")) + } else if r.URL.Path == "/v2/testrepo/supposedlysafechart/blobs/sha256:ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb" { + w.Header().Set("Content-Type", ChartLayerMediaType) + w.WriteHeader(200) + w.Write([]byte("b")) + } else { + w.WriteHeader(500) + } + })) + + u, _ := url.Parse(s.URL) + return fmt.Sprintf("localhost:%s", u.Port()) +} diff --git a/internal/experimental/registry/util.go b/internal/experimental/registry/registry_util.go similarity index 57% rename from internal/experimental/registry/util.go rename to internal/experimental/registry/registry_util.go index 697a890e3..dd8cf79a4 100644 --- a/internal/experimental/registry/util.go +++ b/internal/experimental/registry/registry_util.go @@ -17,41 +17,24 @@ limitations under the License. package registry // import "helm.sh/helm/v3/internal/experimental/registry" import ( + "bytes" "context" - "fmt" "io" - "time" - orascontext "github.com/deislabs/oras/pkg/context" - units "github.com/docker/go-units" + orascontext "github.com/oras-project/oras-go/pkg/context" "github.com/sirupsen/logrus" -) -// byteCountBinary produces a human-readable file size -func byteCountBinary(b int64) string { - const unit = 1024 - if b < unit { - return fmt.Sprintf("%d B", b) - } - div, exp := int64(unit), 0 - for n := b / unit; n >= unit; n /= unit { - div *= unit - exp++ - } - return fmt.Sprintf("%.1f %ciB", float64(b)/float64(div), "KMGTPE"[exp]) -} + "helm.sh/helm/v3/pkg/chart" + "helm.sh/helm/v3/pkg/chart/loader" +) -// shortDigest returns first 7 characters of a sha256 digest -func shortDigest(digest string) string { - if len(digest) == 64 { - return digest[:7] +// extractChartMeta is used to extract a chart metadata from a byte array +func extractChartMeta(chartData []byte) (*chart.Metadata, error) { + ch, err := loader.LoadArchive(bytes.NewReader(chartData)) + if err != nil { + return nil, err } - return digest -} - -// timeAgo returns a human-readable timestamp representing time that has passed -func timeAgo(t time.Time) string { - return units.HumanDuration(time.Now().UTC().Sub(t)) + return ch.Metadata, nil } // ctx retrieves a fresh context. diff --git a/pkg/action/action_test.go b/pkg/action/action_test.go index fedf260fb..f8bdff3b7 100644 --- a/pkg/action/action_test.go +++ b/pkg/action/action_test.go @@ -16,15 +16,11 @@ limitations under the License. package action import ( - "context" "flag" "io/ioutil" - "net/http" "os" - "path/filepath" "testing" - dockerauth "github.com/deislabs/oras/pkg/auth/docker" fakeclientset "k8s.io/client-go/kubernetes/fake" "helm.sh/helm/v3/internal/experimental/registry" @@ -42,16 +38,6 @@ var verbose = flag.Bool("test.log", false, "enable test logging") func actionConfigFixture(t *testing.T) *Configuration { t.Helper() - client, err := dockerauth.NewClient() - if err != nil { - t.Fatal(err) - } - - resolver, err := client.Resolver(context.Background(), http.DefaultClient, false) - if err != nil { - t.Fatal(err) - } - tdir, err := ioutil.TempDir("", "helm-action-test") if err != nil { t.Fatal(err) @@ -59,23 +45,7 @@ func actionConfigFixture(t *testing.T) *Configuration { t.Cleanup(func() { os.RemoveAll(tdir) }) - cache, err := registry.NewCache( - registry.CacheOptDebug(true), - registry.CacheOptRoot(filepath.Join(tdir, registry.CacheRootDir)), - ) - if err != nil { - t.Fatal(err) - } - - registryClient, err := registry.NewClient( - registry.ClientOptAuthorizer(®istry.Authorizer{ - Client: client, - }), - registry.ClientOptResolver(®istry.Resolver{ - Resolver: resolver, - }), - registry.ClientOptCache(cache), - ) + registryClient, err := registry.NewClient() if err != nil { t.Fatal(err) } diff --git a/pkg/action/chart_export.go b/pkg/action/chart_export.go deleted file mode 100644 index 75840d8bc..000000000 --- a/pkg/action/chart_export.go +++ /dev/null @@ -1,63 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package action - -import ( - "fmt" - "io" - "path/filepath" - - "helm.sh/helm/v3/internal/experimental/registry" - "helm.sh/helm/v3/pkg/chartutil" -) - -// ChartExport performs a chart export operation. -type ChartExport struct { - cfg *Configuration - - Destination string -} - -// NewChartExport creates a new ChartExport object with the given configuration. -func NewChartExport(cfg *Configuration) *ChartExport { - return &ChartExport{ - cfg: cfg, - } -} - -// Run executes the chart export operation -func (a *ChartExport) Run(out io.Writer, ref string) error { - r, err := registry.ParseReference(ref) - if err != nil { - return err - } - - ch, err := a.cfg.RegistryClient.LoadChart(r) - if err != nil { - return err - } - - // Save the chart to local destination directory - err = chartutil.SaveDir(ch, a.Destination) - if err != nil { - return err - } - - d := filepath.Join(a.Destination, ch.Metadata.Name) - fmt.Fprintf(out, "Exported chart to %s/\n", d) - return nil -} diff --git a/pkg/action/chart_list.go b/pkg/action/chart_list.go deleted file mode 100644 index ba49a887d..000000000 --- a/pkg/action/chart_list.go +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package action - -import ( - "io" - - "helm.sh/helm/v3/internal/experimental/registry" -) - -// ChartList performs a chart list operation. -type ChartList struct { - cfg *Configuration - ColumnWidth uint -} - -// NewChartList creates a new ChartList object with the given configuration. -func NewChartList(cfg *Configuration) *ChartList { - return &ChartList{ - cfg: cfg, - } -} - -// Run executes the chart list operation -func (a *ChartList) Run(out io.Writer) error { - client := a.cfg.RegistryClient - opt := registry.ClientOptColumnWidth(a.ColumnWidth) - opt(client) - return client.PrintChartTable() -} diff --git a/pkg/action/chart_pull.go b/pkg/action/chart_pull.go deleted file mode 100644 index 896755201..000000000 --- a/pkg/action/chart_pull.go +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package action - -import ( - "io" - - "helm.sh/helm/v3/internal/experimental/registry" -) - -// ChartPull performs a chart pull operation. -type ChartPull struct { - cfg *Configuration -} - -// NewChartPull creates a new ChartPull object with the given configuration. -func NewChartPull(cfg *Configuration) *ChartPull { - return &ChartPull{ - cfg: cfg, - } -} - -// Run executes the chart pull operation -func (a *ChartPull) Run(out io.Writer, ref string) error { - r, err := registry.ParseReference(ref) - if err != nil { - return err - } - return a.cfg.RegistryClient.PullChartToCache(r) -} diff --git a/pkg/action/chart_push.go b/pkg/action/chart_push.go deleted file mode 100644 index 91ec49d38..000000000 --- a/pkg/action/chart_push.go +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package action - -import ( - "io" - - "helm.sh/helm/v3/internal/experimental/registry" -) - -// ChartPush performs a chart push operation. -type ChartPush struct { - cfg *Configuration -} - -// NewChartPush creates a new ChartPush object with the given configuration. -func NewChartPush(cfg *Configuration) *ChartPush { - return &ChartPush{ - cfg: cfg, - } -} - -// Run executes the chart push operation -func (a *ChartPush) Run(out io.Writer, ref string) error { - r, err := registry.ParseReference(ref) - if err != nil { - return err - } - return a.cfg.RegistryClient.PushChart(r) -} diff --git a/pkg/action/chart_remove.go b/pkg/action/chart_remove.go deleted file mode 100644 index 3c0fc2ed7..000000000 --- a/pkg/action/chart_remove.go +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package action - -import ( - "io" - - "helm.sh/helm/v3/internal/experimental/registry" -) - -// ChartRemove performs a chart remove operation. -type ChartRemove struct { - cfg *Configuration -} - -// NewChartRemove creates a new ChartRemove object with the given configuration. -func NewChartRemove(cfg *Configuration) *ChartRemove { - return &ChartRemove{ - cfg: cfg, - } -} - -// Run executes the chart remove operation -func (a *ChartRemove) Run(out io.Writer, ref string) error { - r, err := registry.ParseReference(ref) - if err != nil { - return err - } - return a.cfg.RegistryClient.RemoveChart(r) -} diff --git a/pkg/action/chart_save.go b/pkg/action/chart_save.go deleted file mode 100644 index 14a2d7c3c..000000000 --- a/pkg/action/chart_save.go +++ /dev/null @@ -1,51 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package action - -import ( - "io" - - "helm.sh/helm/v3/internal/experimental/registry" - "helm.sh/helm/v3/pkg/chart" -) - -// ChartSave performs a chart save operation. -type ChartSave struct { - cfg *Configuration -} - -// NewChartSave creates a new ChartSave object with the given configuration. -func NewChartSave(cfg *Configuration) *ChartSave { - return &ChartSave{ - cfg: cfg, - } -} - -// Run executes the chart save operation -func (a *ChartSave) Run(out io.Writer, ch *chart.Chart, ref string) error { - r, err := registry.ParseReference(ref) - if err != nil { - return err - } - - // If no tag is present, use the chart version - if r.Tag == "" { - r.Tag = ch.Metadata.Version - } - - return a.cfg.RegistryClient.SaveChart(ch, r) -} diff --git a/pkg/action/chart_save_test.go b/pkg/action/chart_save_test.go deleted file mode 100644 index 4fd991a4e..000000000 --- a/pkg/action/chart_save_test.go +++ /dev/null @@ -1,70 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package action - -import ( - "io/ioutil" - "testing" - - "helm.sh/helm/v3/internal/experimental/registry" -) - -func chartSaveAction(t *testing.T) *ChartSave { - t.Helper() - config := actionConfigFixture(t) - action := NewChartSave(config) - return action -} - -func TestChartSave(t *testing.T) { - action := chartSaveAction(t) - - input := buildChart() - if err := action.Run(ioutil.Discard, input, "localhost:5000/test:0.2.0"); err != nil { - t.Error(err) - } - - ref, err := registry.ParseReference("localhost:5000/test:0.2.0") - if err != nil { - t.Fatal(err) - } - - if _, err := action.cfg.RegistryClient.LoadChart(ref); err != nil { - t.Error(err) - } - - // now let's check if `helm chart save` can use the chart version when the tag is not present - if err := action.Run(ioutil.Discard, input, "localhost:5000/test"); err != nil { - t.Error(err) - } - - ref, err = registry.ParseReference("localhost:5000/test") - if err != nil { - t.Fatal(err) - } - - // TODO: guess latest based on semver? - _, err = action.cfg.RegistryClient.LoadChart(ref) - if err == nil { - t.Error("Expected error parsing ref without tag") - } - - ref.Tag = "0.1.0" - if _, err := action.cfg.RegistryClient.LoadChart(ref); err != nil { - t.Error(err) - } -} diff --git a/pkg/action/install.go b/pkg/action/install.go index c33d6bf3c..734f7f436 100644 --- a/pkg/action/install.go +++ b/pkg/action/install.go @@ -661,6 +661,14 @@ func (c *ChartPathOptions) LocateChart(name string, settings *cli.EnvSettings) ( RepositoryConfig: settings.RepositoryConfig, RepositoryCache: settings.RepositoryCache, } + + if strings.HasPrefix(name, "oci://") { + if version == "" { + return "", errors.Errorf("--version flag is explicitly required for OCI registries") + } + dl.Options = append(dl.Options, getter.WithTagName(version)) + } + if c.Verify { dl.Verify = downloader.VerifyAlways } @@ -692,5 +700,10 @@ func (c *ChartPathOptions) LocateChart(name string, settings *cli.EnvSettings) ( if version != "" { atVersion = fmt.Sprintf(" at version %q", version) } - return filename, errors.Errorf("failed to download %q%s (hint: running `helm repo update` may help)", name, atVersion) + + hint := "running `helm repo update` may help" + if strings.HasPrefix(name, "oci://") { + hint = "running `helm registry login` may help)" + } + return filename, errors.Errorf("failed to download %q%s (hint: %s)", name, atVersion, hint) } diff --git a/pkg/action/push.go b/pkg/action/push.go new file mode 100644 index 000000000..bd37818b8 --- /dev/null +++ b/pkg/action/push.go @@ -0,0 +1,73 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package action + +import ( + "strings" + + "helm.sh/helm/v3/pkg/cli" + "helm.sh/helm/v3/pkg/pusher" + "helm.sh/helm/v3/pkg/uploader" +) + +// Push is the action for uploading a chart. +// +// It provides the implementation of 'helm push'. +type Push struct { + Settings *cli.EnvSettings + WithProv bool + cfg *Configuration +} + +// PushOpt is a type of function that sets options for a push action. +type PushOpt func(*Push) + +// WithPushConfig sets the cfg field on the push configuration object. +func WithPushConfig(cfg *Configuration) PushOpt { + return func(p *Push) { + p.cfg = cfg + } +} + +// NewPushWithOpts creates a new push, with configuration options. +func NewPushWithOpts(opts ...PushOpt) *Push { + p := &Push{} + for _, fn := range opts { + fn(p) + } + return p +} + +// Run executes 'helm push' against the given chart archive. +func (p *Push) Run(chartRef string, remote string) (string, error) { + var out strings.Builder + + c := uploader.ChartUploader{ + Out: &out, + Pushers: pusher.All(p.Settings), + Options: []pusher.Option{ + pusher.WithProvenance(p.WithProv), + }, + } + + if strings.HasPrefix(remote, "oci://") { + c.Options = append(c.Options, pusher.WithRegistryClient(p.cfg.RegistryClient)) + } + + err := c.UploadTo(chartRef, remote) + return out.String(), err +} diff --git a/pkg/action/registry_login.go b/pkg/action/registry_login.go index 00f6e2644..e09347787 100644 --- a/pkg/action/registry_login.go +++ b/pkg/action/registry_login.go @@ -18,6 +18,8 @@ package action import ( "io" + + "helm.sh/helm/v3/internal/experimental/registry" ) // RegistryLogin performs a registry login operation. @@ -34,5 +36,9 @@ func NewRegistryLogin(cfg *Configuration) *RegistryLogin { // Run executes the registry login operation func (a *RegistryLogin) Run(out io.Writer, hostname string, username string, password string, insecure bool) error { - return a.cfg.RegistryClient.Login(hostname, username, password, insecure) + _, err := a.cfg.RegistryClient.Login( + hostname, + registry.LoginOptBasicAuth(username, password), + registry.LoginOptInsecure(insecure)) + return err } diff --git a/pkg/action/registry_logout.go b/pkg/action/registry_logout.go index 69add4163..6fad56e45 100644 --- a/pkg/action/registry_logout.go +++ b/pkg/action/registry_logout.go @@ -34,5 +34,6 @@ func NewRegistryLogout(cfg *Configuration) *RegistryLogout { // Run executes the registry logout operation func (a *RegistryLogout) Run(out io.Writer, hostname string) error { - return a.cfg.RegistryClient.Logout(hostname) + _, err := a.cfg.RegistryClient.Logout(hostname) + return err } diff --git a/pkg/getter/ocigetter.go b/pkg/getter/ocigetter.go index 3f85b9862..025d44952 100644 --- a/pkg/getter/ocigetter.go +++ b/pkg/getter/ocigetter.go @@ -40,21 +40,29 @@ func (g *OCIGetter) get(href string) (*bytes.Buffer, error) { client := g.opts.registryClient ref := strings.TrimPrefix(href, "oci://") + + var pullOpts []registry.PullOption + requestingProv := strings.HasSuffix(ref, ".prov") + if requestingProv { + ref = strings.TrimSuffix(ref, ".prov") + pullOpts = append(pullOpts, + registry.PullOptWithChart(false), + registry.PullOptWithProv(true)) + } + if version := g.opts.version; version != "" { ref = fmt.Sprintf("%s:%s", ref, version) } - r, err := registry.ParseReference(ref) + result, err := client.Pull(ref, pullOpts...) if err != nil { return nil, err } - buf, err := client.PullChart(r) - if err != nil { - return nil, err + if requestingProv { + return bytes.NewBuffer(result.Prov.Data), nil } - - return buf, nil + return bytes.NewBuffer(result.Chart.Data), nil } // NewOCIGetter constructs a valid http/https client as a Getter diff --git a/pkg/pusher/doc.go b/pkg/pusher/doc.go new file mode 100644 index 000000000..f835726a3 --- /dev/null +++ b/pkg/pusher/doc.go @@ -0,0 +1,21 @@ +/* +Copyright The Helm Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/*Package pusher provides a generalized tool for uploading data by scheme. + +This provides a method by which the plugin system can load arbitrary protocol +handlers based upon a URL scheme. +*/ +package pusher diff --git a/pkg/pusher/ocipusher.go b/pkg/pusher/ocipusher.go new file mode 100644 index 000000000..034113634 --- /dev/null +++ b/pkg/pusher/ocipusher.go @@ -0,0 +1,95 @@ +/* +Copyright The Helm Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package pusher + +import ( + "fmt" + "io/ioutil" + "path" + "strings" + + "helm.sh/helm/v3/internal/experimental/registry" + "helm.sh/helm/v3/pkg/chart/loader" +) + +// OCIPusher is the default OCI backend handler +type OCIPusher struct { + opts options +} + +// Push performs a Push from repo.Pusher. +func (pusher *OCIPusher) Push(chartRef, href string, options ...Option) error { + for _, opt := range options { + opt(&pusher.opts) + } + return pusher.push(chartRef, href) +} + +func (pusher *OCIPusher) push(chartRef, href string) error { + meta, err := loader.Load(chartRef) + if err != nil { + return err + } + + client := pusher.opts.registryClient + + chartBytes, err := ioutil.ReadFile(chartRef) + if err != nil { + return err + } + + var pushOpts []registry.PushOption + var provBytes []byte + if pusher.opts.withProv { + provRef := fmt.Sprintf("%s.prov", chartRef) + provBytes, err = ioutil.ReadFile(provRef) + if err != nil { + return err + } + pushOpts = append(pushOpts, registry.PushOptProvData(provBytes)) + } + + ref := fmt.Sprintf("%s:%s", + path.Join(strings.TrimPrefix(href, "oci://"), meta.Metadata.Name), + meta.Metadata.Version) + + _, err = client.Push(chartBytes, ref, pushOpts...) + if err != nil { + return err + } + + return nil +} + +// NewOCIPusher constructs a valid OCI client as a Pusher +func NewOCIPusher(ops ...Option) (Pusher, error) { + registryClient, err := registry.NewClient() + if err != nil { + return nil, err + } + + client := OCIPusher{ + opts: options{ + registryClient: registryClient, + }, + } + + for _, opt := range ops { + opt(&client.opts) + } + + return &client, nil +} diff --git a/pkg/pusher/ocipusher_test.go b/pkg/pusher/ocipusher_test.go new file mode 100644 index 000000000..7a5026d12 --- /dev/null +++ b/pkg/pusher/ocipusher_test.go @@ -0,0 +1,30 @@ +/* +Copyright The Helm Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package pusher + +import ( + "testing" +) + +func TestNewOCIPusher(t *testing.T) { + testfn := func(ops *options) { + if ops.registryClient == nil { + t.Fatalf("the OCIPusher's registryClient should not be null") + } + } + + NewOCIPusher(testfn) +} diff --git a/pkg/pusher/pusher.go b/pkg/pusher/pusher.go new file mode 100644 index 000000000..dea8d962a --- /dev/null +++ b/pkg/pusher/pusher.go @@ -0,0 +1,103 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package pusher + +import ( + "github.com/pkg/errors" + + "helm.sh/helm/v3/internal/experimental/registry" + "helm.sh/helm/v3/pkg/cli" +) + +// options are generic parameters to be provided to the pusher during instantiation. +// +// Pushers may or may not ignore these parameters as they are passed in. +type options struct { + withProv bool + registryClient *registry.Client +} + +// Option allows specifying various settings configurable by the user for overriding the defaults +// used when performing Push operations with the Pusher. +type Option func(*options) + +// WithRegistryClient sets the registryClient option. +func WithRegistryClient(client *registry.Client) Option { + return func(opts *options) { + opts.registryClient = client + } +} + +// WithProvenance sets the withProv option. +func WithProvenance(withProv bool) Option { + return func(opts *options) { + opts.withProv = withProv + } +} + +// Pusher is an interface to support upload to the specified URL. +type Pusher interface { + // Push file content by url string + Push(chartRef, url string, options ...Option) error +} + +// Constructor is the function for every pusher which creates a specific instance +// according to the configuration +type Constructor func(options ...Option) (Pusher, error) + +// Provider represents any pusher and the schemes that it supports. +type Provider struct { + Schemes []string + New Constructor +} + +// Provides returns true if the given scheme is supported by this Provider. +func (p Provider) Provides(scheme string) bool { + for _, i := range p.Schemes { + if i == scheme { + return true + } + } + return false +} + +// Providers is a collection of Provider objects. +type Providers []Provider + +// ByScheme returns a Provider that handles the given scheme. +// +// If no provider handles this scheme, this will return an error. +func (p Providers) ByScheme(scheme string) (Pusher, error) { + for _, pp := range p { + if pp.Provides(scheme) { + return pp.New() + } + } + return nil, errors.Errorf("scheme %q not supported", scheme) +} + +var ociProvider = Provider{ + Schemes: []string{"oci"}, + New: NewOCIPusher, +} + +// All finds all of the registered pushers as a list of Provider instances. +// Currently, just the built-in pushers are collected. +func All(settings *cli.EnvSettings) Providers { + result := Providers{ociProvider} + return result +} diff --git a/pkg/pusher/pusher_test.go b/pkg/pusher/pusher_test.go new file mode 100644 index 000000000..5e289bda9 --- /dev/null +++ b/pkg/pusher/pusher_test.go @@ -0,0 +1,67 @@ +/* +Copyright The Helm Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package pusher + +import ( + "testing" + + "helm.sh/helm/v3/pkg/cli" +) + +func TestProvider(t *testing.T) { + p := Provider{ + []string{"one", "three"}, + func(_ ...Option) (Pusher, error) { return nil, nil }, + } + + if !p.Provides("three") { + t.Error("Expected provider to provide three") + } +} + +func TestProviders(t *testing.T) { + ps := Providers{ + {[]string{"one", "three"}, func(_ ...Option) (Pusher, error) { return nil, nil }}, + {[]string{"two", "four"}, func(_ ...Option) (Pusher, error) { return nil, nil }}, + } + + if _, err := ps.ByScheme("one"); err != nil { + t.Error(err) + } + if _, err := ps.ByScheme("four"); err != nil { + t.Error(err) + } + + if _, err := ps.ByScheme("five"); err == nil { + t.Error("Did not expect handler for five") + } +} + +func TestAll(t *testing.T) { + env := cli.New() + all := All(env) + if len(all) != 1 { + t.Errorf("expected 1 provider (OCI), got %d", len(all)) + } +} + +func TestByScheme(t *testing.T) { + env := cli.New() + g := All(env) + if _, err := g.ByScheme("oci"); err != nil { + t.Error(err) + } +} diff --git a/pkg/repo/repotest/server.go b/pkg/repo/repotest/server.go index 94b5ce7f9..56585a749 100644 --- a/pkg/repo/repotest/server.go +++ b/pkg/repo/repotest/server.go @@ -26,7 +26,6 @@ import ( "testing" "time" - auth "github.com/deislabs/oras/pkg/auth/docker" "github.com/docker/distribution/configuration" "github.com/docker/distribution/registry" _ "github.com/docker/distribution/registry/auth/htpasswd" // used for docker test registry @@ -134,40 +133,25 @@ func (srv *OCIServer) Run(t *testing.T, opts ...OCIServerOpt) { credentialsFile := filepath.Join(srv.Dir, "config.json") - client, err := auth.NewClient(credentialsFile) - if err != nil { - t.Fatalf("error creating auth client") - } - - resolver, err := client.Resolver(context.Background(), http.DefaultClient, false) - if err != nil { - t.Fatalf("error creating resolver") - } - // init test client registryClient, err := ociRegistry.NewClient( ociRegistry.ClientOptDebug(true), ociRegistry.ClientOptWriter(os.Stdout), - ociRegistry.ClientOptAuthorizer(&ociRegistry.Authorizer{ - Client: client, - }), - ociRegistry.ClientOptResolver(&ociRegistry.Resolver{ - Resolver: resolver, - }), + ociRegistry.ClientOptCredentialsFile(credentialsFile), ) if err != nil { t.Fatalf("error creating registry client") } - err = registryClient.Login(srv.RegistryURL, srv.TestUsername, srv.TestPassword, false) + _, err = registryClient.Login( + srv.RegistryURL, + ociRegistry.LoginOptBasicAuth(srv.TestUsername, srv.TestPassword), + ociRegistry.LoginOptInsecure(false)) if err != nil { t.Fatalf("error logging into registry with good credentials") } - ref, err := ociRegistry.ParseReference(fmt.Sprintf("%s/u/ocitestuser/oci-dependent-chart:0.1.0", srv.RegistryURL)) - if err != nil { - t.Fatalf("") - } + ref := fmt.Sprintf("%s/u/ocitestuser/oci-dependent-chart:0.1.0", srv.RegistryURL) err = chartutil.ExpandFile(srv.Dir, filepath.Join(srv.Dir, "oci-dependent-chart-0.1.0.tgz")) if err != nil { @@ -185,31 +169,39 @@ func (srv *OCIServer) Run(t *testing.T, opts ...OCIServerOpt) { t.Fatal("error removing chart before push") } - err = registryClient.SaveChart(ch, ref) + // save it back to disk.. + absPath, err := chartutil.Save(ch, srv.Dir) + if err != nil { + t.Fatal("could not create chart archive") + } + + // load it into memory... + contentBytes, err := ioutil.ReadFile(absPath) if err != nil { - t.Fatal("error saving chart") + t.Fatal("could not load chart into memory") } - err = registryClient.PushChart(ref) + _, err = registryClient.Push(contentBytes, ref) if err != nil { - t.Fatal("error pushing chart") + t.Fatalf("error pushing dependent chart: %s", err) } if cfg.DependingChart != nil { c := cfg.DependingChart - dependingRef, err := ociRegistry.ParseReference(fmt.Sprintf("%s/u/ocitestuser/oci-depending-chart:1.2.3", srv.RegistryURL)) - if err != nil { - t.Fatal("error parsing reference for depending chart reference") - } + dependingRef := fmt.Sprintf("%s/u/ocitestuser/%s:%s", + srv.RegistryURL, c.Metadata.Name, c.Metadata.Version) - err = registryClient.SaveChart(c, dependingRef) + // load it into memory... + absPath := filepath.Join(srv.Dir, + fmt.Sprintf("%s-%s.tgz", c.Metadata.Name, c.Metadata.Version)) + contentBytes, err := ioutil.ReadFile(absPath) if err != nil { - t.Fatal("error saving depending chart") + t.Fatal("could not load chart into memory") } - err = registryClient.PushChart(dependingRef) + _, err = registryClient.Push(contentBytes, dependingRef) if err != nil { - t.Fatal("error pushing depending chart") + t.Fatalf("error pushing depending chart: %s", err) } } diff --git a/pkg/uploader/chart_uploader.go b/pkg/uploader/chart_uploader.go new file mode 100644 index 000000000..02cee1324 --- /dev/null +++ b/pkg/uploader/chart_uploader.go @@ -0,0 +1,58 @@ +/* +Copyright The Helm Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package uploader + +import ( + "io" + "net/url" + + "github.com/pkg/errors" + + "helm.sh/helm/v3/internal/experimental/registry" + "helm.sh/helm/v3/pkg/pusher" +) + +// ChartUploader handles uploading a chart. +type ChartUploader struct { + // Out is the location to write warning and info messages. + Out io.Writer + // Pusher collection for the operation + Pushers pusher.Providers + // Options provide parameters to be passed along to the Pusher being initialized. + Options []pusher.Option + // RegistryClient is a client for interacting with registries. + RegistryClient *registry.Client +} + +// UploadTo uploads a chart. Depending on the settings, it may also upload a provenance file. +func (c *ChartUploader) UploadTo(ref, remote string) error { + u, err := url.Parse(remote) + if err != nil { + return errors.Errorf("invalid chart URL format: %s", remote) + } + + pusher, err := c.Pushers.ByScheme(u.Scheme) + if err != nil { + return err + } + + err = pusher.Push(ref, u.String(), c.Options...) + if err != nil { + return err + } + + return nil +} diff --git a/pkg/uploader/doc.go b/pkg/uploader/doc.go new file mode 100644 index 000000000..45eacbbf5 --- /dev/null +++ b/pkg/uploader/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Helm Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/*Package uploader provides a library for uploading charts. + +This package contains tools for uploading charts to registries. +*/ +package uploader