[kse-2112] add extension version controller (#6399)

Signed-off-by: ks-ci-bot <ks-ci-bot@kubesphere.io>
Co-authored-by: ks-ci-bot <ks-ci-bot@kubesphere.io>
This commit is contained in:
KubeSphere CI Bot
2025-03-11 10:13:47 +08:00
committed by GitHub
parent 7e2cafd15b
commit 0556934ecc
16 changed files with 669 additions and 506 deletions

View File

@@ -44,6 +44,7 @@ type ExtensionSpec struct {
// ExtensionVersionSpec contains the details of a specific version extension.
type ExtensionVersionSpec struct {
ExtensionInfo `json:",inline"`
Name string `json:"-"`
Version string `json:"version,omitempty"`
Keywords []string `json:"keywords,omitempty"`
Sources []string `json:"sources,omitempty"`

View File

@@ -6,6 +6,7 @@ import (
type UpdateStrategy struct {
RegistryPoll `json:"registryPoll,omitempty"`
Timeout metav1.Duration `json:"timeout"`
}
type RegistryPoll struct {
@@ -18,8 +19,6 @@ type BasicAuth struct {
}
type RepositorySpec struct {
// DEPRECATED: the field will remove in future versions, please use url.
Image string `json:"image,omitempty"`
URL string `json:"url,omitempty"`
Description string `json:"description,omitempty"`
BasicAuth *BasicAuth `json:"basicAuth,omitempty"`

View File

@@ -856,6 +856,7 @@ func (in *ServiceAccountList) DeepCopyObject() runtime.Object {
func (in *UpdateStrategy) DeepCopyInto(out *UpdateStrategy) {
*out = *in
out.RegistryPoll = in.RegistryPoll
out.Timeout = in.Timeout
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdateStrategy.

View File

@@ -1,5 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
// Code generated by controller-gen. DO NOT EDIT.

View File

@@ -6,6 +6,7 @@ go 1.22.11
require (
github.com/aws/aws-sdk-go v1.55.5
github.com/pkg/errors v0.9.1
helm.sh/helm/v3 v3.16.2
k8s.io/api v0.31.2
k8s.io/apimachinery v0.31.2
@@ -106,7 +107,6 @@ require (
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.20.5 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect

View File

@@ -4,10 +4,13 @@ import (
"bytes"
"context"
"fmt"
"net"
"net/http"
"net/url"
"strings"
"time"
"github.com/pkg/errors"
"helm.sh/helm/v3/pkg/getter"
helmrepo "helm.sh/helm/v3/pkg/repo"
"kubesphere.io/utils/s3"
@@ -17,7 +20,6 @@ import (
const IndexYaml = "index.yaml"
func LoadRepoIndex(ctx context.Context, u string, cred RepoCredential) (*helmrepo.IndexFile, error) {
if !strings.HasSuffix(u, "/") {
u = fmt.Sprintf("%s/%s", u, IndexYaml)
} else {
@@ -26,12 +28,12 @@ func LoadRepoIndex(ctx context.Context, u string, cred RepoCredential) (*helmrep
resp, err := LoadData(ctx, u, cred)
if err != nil {
return nil, err
return nil, errors.Errorf("can't load data from %s: %v", u, err)
}
indexFile, err := loadIndex(resp.Bytes())
if err != nil {
return nil, err
return nil, errors.Errorf("can't load index file: %v", err)
}
return indexFile, nil
@@ -52,10 +54,10 @@ func loadIndex(data []byte) (*helmrepo.IndexFile, error) {
return i, nil
}
func LoadData(ctx context.Context, u string, cred RepoCredential) (*bytes.Buffer, error) {
func LoadData(_ context.Context, u string, cred RepoCredential) (*bytes.Buffer, error) {
parsedURL, err := url.Parse(u)
if err != nil {
return nil, err
return nil, errors.Errorf("can't parse url: %v", err)
}
var resp *bytes.Buffer
if strings.HasPrefix(u, "s3://") {
@@ -71,22 +73,38 @@ func LoadData(ctx context.Context, u string, cred RepoCredential) (*bytes.Buffer
})
if err != nil {
return nil, err
return nil, errors.Errorf("can't create s3 client: %v", err)
}
data, err := client.Read(p)
if err != nil {
return nil, err
return nil, errors.Errorf("can't read data from s3: %v", err)
}
resp = bytes.NewBuffer(data)
} else {
tlsConf, err := NewTLSConfig(cred.CABundle, cred.InsecureSkipTLSVerify)
if err != nil {
return nil, errors.Errorf("can't create tls config: %v", err)
}
tlsConf.ServerName = parsedURL.Hostname()
transport := &http.Transport{
DisableCompression: true,
DialContext: (&net.Dialer{Timeout: 5 * time.Second, KeepAlive: 30 * time.Second}).DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: tlsConf,
}
// TODO add user-agent
g, _ := getter.NewHTTPGetter()
resp, err = g.Get(parsedURL.String(),
getter.WithTimeout(5*time.Minute),
getter.WithInsecureSkipVerifyTLS(cred.InsecureSkipTLSVerify),
getter.WithTLSClientConfig(cred.CertFile, cred.KeyFile, cred.CAFile),
getter.WithTransport(transport),
getter.WithBasicAuth(cred.Username, cred.Password),
)
if err != nil {
@@ -121,12 +139,8 @@ type RepoCredential struct {
Username string `json:"username,omitempty"`
// chart repository password
Password string `json:"password,omitempty"`
// identify HTTPS client using this SSL certificate file
CertFile string `json:"certFile,omitempty"`
// identify HTTPS client using this SSL key file
KeyFile string `json:"keyFile,omitempty"`
// verify certificates of HTTPS-enabled servers using this CA bundle
CAFile string `json:"caFile,omitempty"`
CABundle string `json:"caBundle,omitempty"`
// skip tls certificate checks for the repository, default is ture
InsecureSkipTLSVerify bool `json:"insecureSkipTLSVerify,omitempty"`

View File

@@ -0,0 +1,38 @@
package helm
import (
"crypto/tls"
"crypto/x509"
"encoding/base64"
"fmt"
"github.com/pkg/errors"
)
func NewTLSConfig(caBundle string, insecureSkipTLSVerify bool) (*tls.Config, error) {
config := tls.Config{
InsecureSkipVerify: insecureSkipTLSVerify,
}
if caBundle != "" {
caCerts, err := base64.StdEncoding.DecodeString(caBundle)
if err != nil {
return nil, fmt.Errorf("failed to decode caBundle: %v", err)
}
cp, err := certPoolFromCABundle(caCerts)
if err != nil {
return nil, err
}
config.RootCAs = cp
}
return &config, nil
}
func certPoolFromCABundle(caCerts []byte) (*x509.CertPool, error) {
cp := x509.NewCertPool()
if !cp.AppendCertsFromPEM(caCerts) {
return nil, errors.Errorf("failed to append certificates from caBundle")
}
return cp, nil
}