mirror of
https://github.com/portainer/portainer.git
synced 2026-06-23 07:20:13 +00:00
80 lines
2.4 KiB
Go
80 lines
2.4 KiB
Go
package exec
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
|
|
portainer "github.com/portainer/portainer/api"
|
|
"github.com/portainer/portainer/api/http/proxy"
|
|
"github.com/portainer/portainer/api/http/proxy/factory"
|
|
"github.com/portainer/portainer/api/internal/registryutils"
|
|
|
|
"github.com/docker/cli/cli/config/types"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
var stackNameNormalizeRegex = regexp.MustCompile("[^-_a-z0-9]+")
|
|
|
|
func normalizeStackName(name string) string {
|
|
return stackNameNormalizeRegex.ReplaceAllString(strings.ToLower(name), "")
|
|
}
|
|
|
|
// fetchEndpointProxy returns the Docker host URL for the given endpoint.
|
|
// For remote endpoints it creates a local proxy that handles TLS termination and
|
|
// Portainer agent header injection; for local unix/npipe sockets no proxy is needed.
|
|
func fetchEndpointProxy(proxyManager *proxy.Manager, endpoint *portainer.Endpoint) (string, *factory.ProxyServer, error) {
|
|
if strings.HasPrefix(endpoint.URL, "unix://") || strings.HasPrefix(endpoint.URL, "npipe://") {
|
|
return "", nil, nil
|
|
}
|
|
|
|
proxy, err := proxyManager.CreateAgentProxyServer(endpoint)
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
|
|
return fmt.Sprintf("tcp://127.0.0.1:%d", proxy.Port), proxy, nil
|
|
}
|
|
|
|
// portainerRegistriesToAuthConfigs converts registries to Docker auth configs.
|
|
// Callers must ensure ECR tokens are valid before calling this function (e.g. via
|
|
// registryutils.RefreshAndPersistECRTokens with a real DataStoreTx). This function
|
|
// intentionally performs no DB writes to avoid write-lock contention when called inside
|
|
// an active BoltDB write transaction.
|
|
func portainerRegistriesToAuthConfigs(registries []portainer.Registry) []types.AuthConfig {
|
|
var authConfigs []types.AuthConfig
|
|
|
|
for _, r := range registries {
|
|
ac := types.AuthConfig{
|
|
Username: r.Username,
|
|
Password: r.Password,
|
|
ServerAddress: r.URL,
|
|
}
|
|
|
|
if r.Authentication {
|
|
var err error
|
|
|
|
ac.Username, ac.Password, err = getEffectiveRegUsernamePassword(&r)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
}
|
|
|
|
authConfigs = append(authConfigs, ac)
|
|
}
|
|
|
|
return authConfigs
|
|
}
|
|
|
|
func getEffectiveRegUsernamePassword(registry *portainer.Registry) (string, string, error) {
|
|
username, password, err := registryutils.GetRegEffectiveCredential(registry)
|
|
if err != nil {
|
|
log.Warn().
|
|
Err(err).
|
|
Str("RegistryName", registry.Name).
|
|
Msg("Failed to get effective credential. Skip logging with this registry.")
|
|
}
|
|
|
|
return username, password, err
|
|
}
|