mirror of https://github.com/helm/helm.git
Implement changes proposed in HIP 6
For more information, please see the following URL: https://github.com/helm/community/blob/main/hips/hip-0006.md Note: OCI support remains experimental, and you are still required to set HELM_EXPERIMENTAL_OCI=1 in your environment. Signed-off-by: Josh Dolitsky <josh@dolit.ski>
This commit is contained in:
parent
bf486a25cd
commit
00985cad6b
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
8
go.mod
8
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
|
||||
|
|
|
|||
311
go.sum
311
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=
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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())
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)")
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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"
|
||||
)
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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"`
|
||||
}
|
||||
)
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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"`
|
||||
}
|
||||
)
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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"`
|
||||
}
|
||||
)
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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"`
|
||||
}
|
||||
)
|
||||
|
|
@ -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())
|
||||
}
|
||||
|
|
@ -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"
|
||||
|
||||
"helm.sh/helm/v3/pkg/chart"
|
||||
"helm.sh/helm/v3/pkg/chart/loader"
|
||||
)
|
||||
|
||||
// byteCountBinary produces a human-readable file size
|
||||
func byteCountBinary(b int64) string {
|
||||
const unit = 1024
|
||||
if b < unit {
|
||||
return fmt.Sprintf("%d B", b)
|
||||
// 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
|
||||
}
|
||||
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])
|
||||
}
|
||||
|
||||
// shortDigest returns first 7 characters of a sha256 digest
|
||||
func shortDigest(digest string) string {
|
||||
if len(digest) == 64 {
|
||||
return digest[:7]
|
||||
}
|
||||
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.
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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("error saving chart")
|
||||
t.Fatal("could not create chart archive")
|
||||
}
|
||||
|
||||
err = registryClient.PushChart(ref)
|
||||
// load it into memory...
|
||||
contentBytes, err := ioutil.ReadFile(absPath)
|
||||
if err != nil {
|
||||
t.Fatal("error pushing chart")
|
||||
t.Fatal("could not load chart into memory")
|
||||
}
|
||||
|
||||
_, err = registryClient.Push(contentBytes, ref)
|
||||
if err != nil {
|
||||
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))
|
||||
dependingRef := fmt.Sprintf("%s/u/ocitestuser/%s:%s",
|
||||
srv.RegistryURL, c.Metadata.Name, c.Metadata.Version)
|
||||
|
||||
// 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 parsing reference for depending chart reference")
|
||||
t.Fatal("could not load chart into memory")
|
||||
}
|
||||
|
||||
err = registryClient.SaveChart(c, dependingRef)
|
||||
_, err = registryClient.Push(contentBytes, dependingRef)
|
||||
if err != nil {
|
||||
t.Fatal("error saving depending chart")
|
||||
}
|
||||
|
||||
err = registryClient.PushChart(dependingRef)
|
||||
if err != nil {
|
||||
t.Fatal("error pushing depending chart")
|
||||
t.Fatalf("error pushing depending chart: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue