1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-25 08:19:40 +02:00

refactor(helm): helm binary to sdk refactor [r8s-229] (#463)

Co-authored-by: stevensbkang <skan070@gmail.com>
This commit is contained in:
Ali 2025-03-13 12:20:16 +13:00 committed by GitHub
parent 0d25f3f430
commit b5961d79f8
56 changed files with 2222 additions and 819 deletions

View file

@ -49,6 +49,7 @@ import (
"github.com/portainer/portainer/pkg/build"
"github.com/portainer/portainer/pkg/featureflags"
"github.com/portainer/portainer/pkg/libhelm"
libhelmtypes "github.com/portainer/portainer/pkg/libhelm/types"
"github.com/portainer/portainer/pkg/libstack/compose"
"github.com/gofrs/uuid"
@ -169,8 +170,8 @@ func initKubernetesDeployer(kubernetesTokenCacheManager *kubeproxy.TokenCacheMan
return exec.NewKubernetesDeployer(kubernetesTokenCacheManager, kubernetesClientFactory, dataStore, reverseTunnelService, signatureService, proxyManager, assetsPath)
}
func initHelmPackageManager(assetsPath string) (libhelm.HelmPackageManager, error) {
return libhelm.NewHelmPackageManager(libhelm.HelmConfig{BinaryPath: assetsPath})
func initHelmPackageManager() (libhelmtypes.HelmPackageManager, error) {
return libhelm.NewHelmPackageManager()
}
func initAPIKeyService(datastore dataservices.DataStore) apikey.APIKeyService {
@ -437,7 +438,7 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
proxyManager.NewProxyFactory(dataStore, signatureService, reverseTunnelService, dockerClientFactory, kubernetesClientFactory, kubernetesTokenCacheManager, gitService, snapshotService)
helmPackageManager, err := initHelmPackageManager(*flags.Assets)
helmPackageManager, err := initHelmPackageManager()
if err != nil {
log.Fatal().Err(err).Msg("failed initializing helm package manager")
}

View file

@ -10,7 +10,7 @@ import (
)
const (
jsonobject = `{"LogoURL":"","BlackListedLabels":[],"AuthenticationMethod":1,"InternalAuthSettings": {"RequiredPasswordLength": 12}"LDAPSettings":{"AnonymousMode":true,"ReaderDN":"","URL":"","TLSConfig":{"TLS":false,"TLSSkipVerify":false},"StartTLS":false,"SearchSettings":[{"BaseDN":"","Filter":"","UserNameAttribute":""}],"GroupSearchSettings":[{"GroupBaseDN":"","GroupFilter":"","GroupAttribute":""}],"AutoCreateUsers":true},"OAuthSettings":{"ClientID":"","AccessTokenURI":"","AuthorizationURI":"","ResourceURI":"","RedirectURI":"","UserIdentifier":"","Scopes":"","OAuthAutoCreateUsers":false,"DefaultTeamID":0,"SSO":true,"LogoutURI":"","KubeSecretKey":"j0zLVtY/lAWBk62ByyF0uP80SOXaitsABP0TTJX8MhI="},"OpenAMTConfiguration":{"Enabled":false,"MPSServer":"","MPSUser":"","MPSPassword":"","MPSToken":"","CertFileContent":"","CertFileName":"","CertFilePassword":"","DomainName":""},"FeatureFlagSettings":{},"SnapshotInterval":"5m","TemplatesURL":"https://raw.githubusercontent.com/portainer/templates/master/templates-2.0.json","EdgeAgentCheckinInterval":5,"EnableEdgeComputeFeatures":false,"UserSessionTimeout":"8h","KubeconfigExpiry":"0","EnableTelemetry":true,"HelmRepositoryURL":"https://kubernetes.github.io/ingress-nginx","KubectlShellImage":"portainer/kubectl-shell","DisplayDonationHeader":false,"DisplayExternalContributors":false,"EnableHostManagementFeatures":false,"AllowVolumeBrowserForRegularUsers":false,"AllowBindMountsForRegularUsers":false,"AllowPrivilegedModeForRegularUsers":false,"AllowHostNamespaceForRegularUsers":false,"AllowStackManagementForRegularUsers":false,"AllowDeviceMappingForRegularUsers":false,"AllowContainerCapabilitiesForRegularUsers":false}`
jsonobject = `{"LogoURL":"","BlackListedLabels":[],"AuthenticationMethod":1,"InternalAuthSettings": {"RequiredPasswordLength": 12}"LDAPSettings":{"AnonymousMode":true,"ReaderDN":"","URL":"","TLSConfig":{"TLS":false,"TLSSkipVerify":false},"StartTLS":false,"SearchSettings":[{"BaseDN":"","Filter":"","UserNameAttribute":""}],"GroupSearchSettings":[{"GroupBaseDN":"","GroupFilter":"","GroupAttribute":""}],"AutoCreateUsers":true},"OAuthSettings":{"ClientID":"","AccessTokenURI":"","AuthorizationURI":"","ResourceURI":"","RedirectURI":"","UserIdentifier":"","Scopes":"","OAuthAutoCreateUsers":false,"DefaultTeamID":0,"SSO":true,"LogoutURI":"","KubeSecretKey":"j0zLVtY/lAWBk62ByyF0uP80SOXaitsABP0TTJX8MhI="},"OpenAMTConfiguration":{"Enabled":false,"MPSServer":"","MPSUser":"","MPSPassword":"","MPSToken":"","CertFileContent":"","CertFileName":"","CertFilePassword":"","DomainName":""},"FeatureFlagSettings":{},"SnapshotInterval":"5m","TemplatesURL":"https://raw.githubusercontent.com/portainer/templates/master/templates-2.0.json","EdgeAgentCheckinInterval":5,"EnableEdgeComputeFeatures":false,"UserSessionTimeout":"8h","KubeconfigExpiry":"0","EnableTelemetry":true,"HelmRepositoryURL":"https://charts.bitnami.com/bitnami","KubectlShellImage":"portainer/kubectl-shell","DisplayDonationHeader":false,"DisplayExternalContributors":false,"EnableHostManagementFeatures":false,"AllowVolumeBrowserForRegularUsers":false,"AllowBindMountsForRegularUsers":false,"AllowPrivilegedModeForRegularUsers":false,"AllowHostNamespaceForRegularUsers":false,"AllowStackManagementForRegularUsers":false,"AllowDeviceMappingForRegularUsers":false,"AllowContainerCapabilitiesForRegularUsers":false}`
passphrase = "my secret key"
)

View file

@ -605,7 +605,7 @@
"GlobalDeploymentOptions": {
"hideStacksFunctionality": false
},
"HelmRepositoryURL": "",
"HelmRepositoryURL": "https://charts.bitnami.com/bitnami",
"InternalAuthSettings": {
"RequiredPasswordLength": 12
},

View file

@ -1,6 +1,7 @@
package helm
import (
"fmt"
"net/http"
portainer "github.com/portainer/portainer/api"
@ -8,8 +9,8 @@ import (
"github.com/portainer/portainer/api/http/middlewares"
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/kubernetes"
"github.com/portainer/portainer/pkg/libhelm"
"github.com/portainer/portainer/pkg/libhelm/options"
libhelmtypes "github.com/portainer/portainer/pkg/libhelm/types"
httperror "github.com/portainer/portainer/pkg/libhttp/error"
"github.com/gorilla/mux"
@ -23,11 +24,11 @@ type Handler struct {
jwtService portainer.JWTService
kubeClusterAccessService kubernetes.KubeClusterAccessService
kubernetesDeployer portainer.KubernetesDeployer
helmPackageManager libhelm.HelmPackageManager
helmPackageManager libhelmtypes.HelmPackageManager
}
// NewHandler creates a handler to manage endpoint group operations.
func NewHandler(bouncer security.BouncerService, dataStore dataservices.DataStore, jwtService portainer.JWTService, kubernetesDeployer portainer.KubernetesDeployer, helmPackageManager libhelm.HelmPackageManager, kubeClusterAccessService kubernetes.KubeClusterAccessService) *Handler {
func NewHandler(bouncer security.BouncerService, dataStore dataservices.DataStore, jwtService portainer.JWTService, kubernetesDeployer portainer.KubernetesDeployer, helmPackageManager libhelmtypes.HelmPackageManager, kubeClusterAccessService kubernetes.KubeClusterAccessService) *Handler {
h := &Handler{
Router: mux.NewRouter(),
requestBouncer: bouncer,
@ -57,7 +58,7 @@ func NewHandler(bouncer security.BouncerService, dataStore dataservices.DataStor
}
// NewTemplateHandler creates a template handler to manage environment(endpoint) group operations.
func NewTemplateHandler(bouncer security.BouncerService, helmPackageManager libhelm.HelmPackageManager) *Handler {
func NewTemplateHandler(bouncer security.BouncerService, helmPackageManager libhelmtypes.HelmPackageManager) *Handler {
h := &Handler{
Router: mux.NewRouter(),
helmPackageManager: helmPackageManager,
@ -78,7 +79,7 @@ func NewTemplateHandler(bouncer security.BouncerService, helmPackageManager libh
// getHelmClusterAccess obtains the core k8s cluster access details from request.
// The cluster access includes the cluster server url, the user's bearer token and the tls certificate.
// The cluster access is passed in as kube config CLI params to helm binary.
// The cluster access is passed in as kube config CLI params to helm.
func (handler *Handler) getHelmClusterAccess(r *http.Request) (*options.KubernetesClusterAccess, *httperror.HandlerError) {
endpoint, err := middlewares.FetchEndpoint(r)
if err != nil {
@ -107,6 +108,9 @@ func (handler *Handler) getHelmClusterAccess(r *http.Request) (*options.Kubernet
kubeConfigInternal := handler.kubeClusterAccessService.GetClusterDetails(hostURL, endpoint.ID, true)
return &options.KubernetesClusterAccess{
ClusterName: fmt.Sprintf("%s-%s", "portainer-cluster", endpoint.Name),
ContextName: fmt.Sprintf("%s-%s", "portainer-ctx", endpoint.Name),
UserName: fmt.Sprintf("%s-%s", "portainer-sa-user", tokenData.Username),
ClusterServerURL: kubeConfigInternal.ClusterServerURL,
CertificateAuthorityFile: kubeConfigInternal.CertificateAuthorityFile,
AuthToken: bearerToken,

View file

@ -13,8 +13,8 @@ import (
helper "github.com/portainer/portainer/api/internal/testhelpers"
"github.com/portainer/portainer/api/jwt"
"github.com/portainer/portainer/api/kubernetes"
"github.com/portainer/portainer/pkg/libhelm/binary/test"
"github.com/portainer/portainer/pkg/libhelm/options"
"github.com/portainer/portainer/pkg/libhelm/test"
"github.com/stretchr/testify/assert"
)
@ -34,7 +34,7 @@ func Test_helmDelete(t *testing.T) {
is.NoError(err, "Error initiating jwt service")
kubernetesDeployer := exectest.NewKubernetesDeployer()
helmPackageManager := test.NewMockHelmBinaryPackageManager("")
helmPackageManager := test.NewMockHelmPackageManager()
kubeClusterAccessService := kubernetes.NewKubeClusterAccessService("", "", "")
h := NewHandler(helper.NewTestRequestBouncer(), store, jwtService, kubernetesDeployer, helmPackageManager, kubeClusterAccessService)

View file

@ -99,15 +99,11 @@ func (handler *Handler) installChart(r *http.Request, p installChartPayload) (*r
}
installOpts := options.InstallOptions{
Name: p.Name,
Chart: p.Chart,
Namespace: p.Namespace,
Repo: p.Repo,
KubernetesClusterAccess: &options.KubernetesClusterAccess{
ClusterServerURL: clusterAccess.ClusterServerURL,
CertificateAuthorityFile: clusterAccess.CertificateAuthorityFile,
AuthToken: clusterAccess.AuthToken,
},
Name: p.Name,
Chart: p.Chart,
Namespace: p.Namespace,
Repo: p.Repo,
KubernetesClusterAccess: clusterAccess,
}
if p.Values != "" {

View file

@ -15,9 +15,9 @@ import (
helper "github.com/portainer/portainer/api/internal/testhelpers"
"github.com/portainer/portainer/api/jwt"
"github.com/portainer/portainer/api/kubernetes"
"github.com/portainer/portainer/pkg/libhelm/binary/test"
"github.com/portainer/portainer/pkg/libhelm/options"
"github.com/portainer/portainer/pkg/libhelm/release"
"github.com/portainer/portainer/pkg/libhelm/test"
"github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert"
@ -38,14 +38,14 @@ func Test_helmInstall(t *testing.T) {
is.NoError(err, "Error initiating jwt service")
kubernetesDeployer := exectest.NewKubernetesDeployer()
helmPackageManager := test.NewMockHelmBinaryPackageManager("")
helmPackageManager := test.NewMockHelmPackageManager()
kubeClusterAccessService := kubernetes.NewKubeClusterAccessService("", "", "")
h := NewHandler(helper.NewTestRequestBouncer(), store, jwtService, kubernetesDeployer, helmPackageManager, kubeClusterAccessService)
is.NotNil(h, "Handler should not fail")
// Install a single chart. We expect to get these values back
options := options.InstallOptions{Name: "nginx-1", Chart: "nginx", Namespace: "default", Repo: "https://kubernetes.github.io/ingress-nginx"}
options := options.InstallOptions{Name: "nginx-1", Chart: "nginx", Namespace: "default", Repo: "https://charts.bitnami.com/bitnami"}
optdata, err := json.Marshal(options)
is.NoError(err)

View file

@ -14,9 +14,9 @@ import (
helper "github.com/portainer/portainer/api/internal/testhelpers"
"github.com/portainer/portainer/api/jwt"
"github.com/portainer/portainer/api/kubernetes"
"github.com/portainer/portainer/pkg/libhelm/binary/test"
"github.com/portainer/portainer/pkg/libhelm/options"
"github.com/portainer/portainer/pkg/libhelm/release"
"github.com/portainer/portainer/pkg/libhelm/test"
"github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert"
@ -37,7 +37,7 @@ func Test_helmList(t *testing.T) {
is.NoError(err, "Error initialising jwt service")
kubernetesDeployer := exectest.NewKubernetesDeployer()
helmPackageManager := test.NewMockHelmBinaryPackageManager("")
helmPackageManager := test.NewMockHelmPackageManager()
kubeClusterAccessService := kubernetes.NewKubeClusterAccessService("", "", "")
h := NewHandler(helper.NewTestRequestBouncer(), store, jwtService, kubernetesDeployer, helmPackageManager, kubeClusterAccessService)

View file

@ -8,19 +8,19 @@ import (
"testing"
helper "github.com/portainer/portainer/api/internal/testhelpers"
"github.com/portainer/portainer/pkg/libhelm/binary/test"
"github.com/portainer/portainer/pkg/libhelm/test"
"github.com/stretchr/testify/assert"
)
func Test_helmRepoSearch(t *testing.T) {
is := assert.New(t)
helmPackageManager := test.NewMockHelmBinaryPackageManager("")
helmPackageManager := test.NewMockHelmPackageManager()
h := NewTemplateHandler(helper.NewTestRequestBouncer(), helmPackageManager)
assert.NotNil(t, h, "Handler should not fail")
repos := []string{"https://kubernetes.github.io/ingress-nginx", "https://portainer.github.io/k8s"}
repos := []string{"https://charts.bitnami.com/bitnami", "https://portainer.github.io/k8s"}
for _, repo := range repos {
t.Run(repo, func(t *testing.T) {

View file

@ -9,14 +9,14 @@ import (
"testing"
helper "github.com/portainer/portainer/api/internal/testhelpers"
"github.com/portainer/portainer/pkg/libhelm/binary/test"
"github.com/portainer/portainer/pkg/libhelm/test"
"github.com/stretchr/testify/assert"
)
func Test_helmShow(t *testing.T) {
is := assert.New(t)
helmPackageManager := test.NewMockHelmBinaryPackageManager("")
helmPackageManager := test.NewMockHelmPackageManager()
h := NewTemplateHandler(helper.NewTestRequestBouncer(), helmPackageManager)
is.NotNil(h, "Handler should not fail")
@ -31,7 +31,7 @@ func Test_helmShow(t *testing.T) {
t.Run(cmd, func(t *testing.T) {
is.NotNil(h, "Handler should not fail")
repoUrlEncoded := url.QueryEscape("https://kubernetes.github.io/ingress-nginx")
repoUrlEncoded := url.QueryEscape("https://charts.bitnami.com/bitnami")
chart := "nginx"
req := httptest.NewRequest("GET", fmt.Sprintf("/templates/helm/%s?repo=%s&chart=%s", cmd, repoUrlEncoded, chart), nil)
rr := httptest.NewRecorder()

View file

@ -46,7 +46,7 @@ type settingsUpdatePayload struct {
// Whether telemetry is enabled
EnableTelemetry *bool `example:"false"`
// Helm repository URL
HelmRepositoryURL *string `example:"https://kubernetes.github.io/ingress-nginx"`
HelmRepositoryURL *string `example:"https://charts.bitnami.com/bitnami"`
// Kubectl Shell Image
KubectlShellImage *string `example:"portainer/kubectl-shell:latest"`
// TrustOnFirstConnect makes Portainer accepting edge agent connection by default

View file

@ -67,7 +67,7 @@ import (
"github.com/portainer/portainer/api/platform"
"github.com/portainer/portainer/api/scheduler"
"github.com/portainer/portainer/api/stacks/deployments"
"github.com/portainer/portainer/pkg/libhelm"
libhelmtypes "github.com/portainer/portainer/pkg/libhelm/types"
"github.com/rs/zerolog/log"
)
@ -103,7 +103,7 @@ type Server struct {
DockerClientFactory *dockerclient.ClientFactory
KubernetesClientFactory *cli.ClientFactory
KubernetesDeployer portainer.KubernetesDeployer
HelmPackageManager libhelm.HelmPackageManager
HelmPackageManager libhelmtypes.HelmPackageManager
Scheduler *scheduler.Scheduler
ShutdownCtx context.Context
ShutdownTrigger context.CancelFunc

View file

@ -588,7 +588,7 @@ type (
// User identifier
UserID UserID `json:"UserId" example:"1"`
// Helm repository URL
URL string `json:"URL" example:"https://kubernetes.github.io/ingress-nginx"`
URL string `json:"URL" example:"https://charts.bitnami.com/bitnami"`
}
// QuayRegistryData represents data required for Quay registry to work
@ -984,8 +984,8 @@ type (
KubeconfigExpiry string `json:"KubeconfigExpiry" example:"24h"`
// Whether telemetry is enabled
EnableTelemetry bool `json:"EnableTelemetry" example:"false"`
// Helm repository URL, defaults to ""
HelmRepositoryURL string `json:"HelmRepositoryURL"`
// Helm repository URL, defaults to "https://charts.bitnami.com/bitnami"
HelmRepositoryURL string `json:"HelmRepositoryURL" example:"https://charts.bitnami.com/bitnami"`
// KubectlImage, defaults to portainer/kubectl-shell
KubectlShellImage string `json:"KubectlShellImage" example:"portainer/kubectl-shell"`
// TrustOnFirstConnect makes Portainer accepting edge agent connection by default
@ -1673,8 +1673,8 @@ const (
DefaultEdgeAgentCheckinIntervalInSeconds = 5
// DefaultTemplatesURL represents the URL to the official templates supported by Portainer
DefaultTemplatesURL = "https://raw.githubusercontent.com/portainer/templates/v3/templates.json"
// DefaultHelmrepositoryURL set to empty string until oci support is added
DefaultHelmRepositoryURL = ""
// DefaultHelmrepositoryURL represents the URL to the official templates supported by Bitnami
DefaultHelmRepositoryURL = "https://charts.bitnami.com/bitnami"
// DefaultUserSessionTimeout represents the default timeout after which the user session is cleared
DefaultUserSessionTimeout = "8h"
// DefaultUserSessionTimeout represents the default timeout after which the user session is cleared