|
|
|
@ -22,9 +22,11 @@ import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"io"
|
|
|
|
|
"io/ioutil"
|
|
|
|
|
"net"
|
|
|
|
|
"net/http"
|
|
|
|
|
"sort"
|
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/Masterminds/semver/v3"
|
|
|
|
|
"github.com/containerd/containerd/remotes"
|
|
|
|
@ -38,6 +40,8 @@ import (
|
|
|
|
|
registryremote "oras.land/oras-go/pkg/registry/remote"
|
|
|
|
|
registryauth "oras.land/oras-go/pkg/registry/remote/auth"
|
|
|
|
|
|
|
|
|
|
"helm.sh/helm/v3/internal/tlsutil"
|
|
|
|
|
"helm.sh/helm/v3/internal/urlutil"
|
|
|
|
|
"helm.sh/helm/v3/internal/version"
|
|
|
|
|
"helm.sh/helm/v3/pkg/chart"
|
|
|
|
|
"helm.sh/helm/v3/pkg/helmpath"
|
|
|
|
@ -60,6 +64,8 @@ type (
|
|
|
|
|
authorizer auth.Client
|
|
|
|
|
registryAuthorizer *registryauth.Client
|
|
|
|
|
resolver remotes.Resolver
|
|
|
|
|
tlsEnabled bool
|
|
|
|
|
chartRef string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ClientOption allows specifying various settings configurable by the user for overriding the defaults
|
|
|
|
@ -85,7 +91,43 @@ func NewClient(options ...ClientOption) (*Client, error) {
|
|
|
|
|
}
|
|
|
|
|
client.authorizer = authClient
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if client.resolver == nil {
|
|
|
|
|
if client.tlsEnabled {
|
|
|
|
|
host, err := urlutil.ExtractHostname(client.chartRef)
|
|
|
|
|
fmt.Println("host name : ", host)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Printf("error :%v\n", err)
|
|
|
|
|
}
|
|
|
|
|
clientOpts, err := tlsutil.ReadCertFromSecDir(host)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return client, errors.Wrapf(err, "Client certificate/directory Not Exist !!")
|
|
|
|
|
}
|
|
|
|
|
cfgtls, err := tlsutil.ClientConfig(clientOpts)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Printf("error :%v\n", err)
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
var rt http.RoundTripper = &http.Transport{
|
|
|
|
|
Dial: (&net.Dialer{
|
|
|
|
|
Timeout: 30 * time.Second,
|
|
|
|
|
KeepAlive: 30 * time.Second,
|
|
|
|
|
}).Dial,
|
|
|
|
|
TLSHandshakeTimeout: 30 * time.Second,
|
|
|
|
|
TLSClientConfig: cfgtls,
|
|
|
|
|
ResponseHeaderTimeout: time.Duration(30 * time.Second),
|
|
|
|
|
DisableKeepAlives: true,
|
|
|
|
|
}
|
|
|
|
|
crosclient := http.Client{Transport: rt, Timeout: 30 * time.Second}
|
|
|
|
|
headers := http.Header{}
|
|
|
|
|
headers.Set("User-Agent", version.GetUserAgent())
|
|
|
|
|
opts := []auth.ResolverOption{auth.WithResolverHeaders(headers), auth.WithResolverClient(&crosclient)}
|
|
|
|
|
resolver, err := client.authorizer.ResolverWithOpts(opts...)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
client.resolver = resolver
|
|
|
|
|
} else {
|
|
|
|
|
headers := http.Header{}
|
|
|
|
|
headers.Set("User-Agent", version.GetUserAgent())
|
|
|
|
|
opts := []auth.ResolverOption{auth.WithResolverHeaders(headers)}
|
|
|
|
@ -95,6 +137,8 @@ func NewClient(options ...ClientOption) (*Client, error) {
|
|
|
|
|
}
|
|
|
|
|
client.resolver = resolver
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
if client.registryAuthorizer == nil {
|
|
|
|
|
client.registryAuthorizer = ®istryauth.Client{
|
|
|
|
|
Header: http.Header{
|
|
|
|
@ -145,6 +189,12 @@ func ClientOptWriter(out io.Writer) ClientOption {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ClientOptChartRef(chartRef string) ClientOption {
|
|
|
|
|
return func(client *Client) {
|
|
|
|
|
client.chartRef = chartRef
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ClientOptCredentialsFile returns a function that sets the credentialsFile setting on a client options set
|
|
|
|
|
func ClientOptCredentialsFile(credentialsFile string) ClientOption {
|
|
|
|
|
return func(client *Client) {
|
|
|
|
@ -152,6 +202,13 @@ func ClientOptCredentialsFile(credentialsFile string) ClientOption {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//ClientOptTwoWayTLSEnable returns a function that sets the client certificate when two-way tls authentication enable
|
|
|
|
|
func ClientOptTwoWayTLSEnable(tlsEnabled bool) ClientOption {
|
|
|
|
|
return func(client *Client) {
|
|
|
|
|
client.tlsEnabled = tlsEnabled
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type (
|
|
|
|
|
// LoginOption allows specifying various settings on login
|
|
|
|
|
LoginOption func(*loginOperation)
|
|
|
|
@ -303,8 +360,9 @@ func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) {
|
|
|
|
|
|
|
|
|
|
numDescriptors := len(descriptors)
|
|
|
|
|
if numDescriptors < minNumDescriptors {
|
|
|
|
|
return nil, fmt.Errorf("manifest does not contain minimum number of descriptors (%d), descriptors found: %d",
|
|
|
|
|
minNumDescriptors, numDescriptors)
|
|
|
|
|
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
|
|
|
|
@ -324,19 +382,22 @@ func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if configDescriptor == nil {
|
|
|
|
|
return nil, fmt.Errorf("could not load config with mediatype %s", ConfigMediaType)
|
|
|
|
|
return nil, errors.New(
|
|
|
|
|
fmt.Sprintf("could not load config with mediatype %s", ConfigMediaType))
|
|
|
|
|
}
|
|
|
|
|
if operation.withChart && chartDescriptor == nil {
|
|
|
|
|
return nil, fmt.Errorf("manifest does not contain a layer with mediatype %s",
|
|
|
|
|
ChartLayerMediaType)
|
|
|
|
|
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, fmt.Errorf("manifest does not contain a layer with mediatype %s",
|
|
|
|
|
ProvLayerMediaType)
|
|
|
|
|
return nil, errors.New(
|
|
|
|
|
fmt.Sprintf("manifest does not contain a layer with mediatype %s",
|
|
|
|
|
ProvLayerMediaType))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
result := &PullResult{
|
|
|
|
|