chore(code): use int ranges in loops BE-10990 (#12028)

pull/10001/merge
andres-portainer 5 months ago committed by GitHub
parent 468c12c75b
commit 31bdb948a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -10,6 +10,7 @@ linters:
- govet
- errorlint
- copyloopvar
- intrange
linters-settings:
depguard:

@ -40,10 +40,12 @@ func Test_generateRandomKey(t *testing.T) {
t.Run("Generated keys are unique", func(t *testing.T) {
keys := make(map[string]bool)
for i := 0; i < 100; i++ {
for range 100 {
key := GenerateRandomKey(8)
_, ok := keys[string(key)]
is.False(ok)
keys[string(key)] = true
}
})

@ -93,6 +93,7 @@ type Func func(ctx context.Context) (any, error)
// Run runs a list of functions returns the results
func Run(ctx context.Context, maxConcurrency int, tasks ...Func) ([]Result, error) {
var wg sync.WaitGroup
resultsChan := make(chan Result, len(tasks))
taskChan := make(chan Func, len(tasks))
@ -101,6 +102,7 @@ func Run(ctx context.Context, maxConcurrency int, tasks ...Func) ([]Result, erro
runTask := func() {
defer wg.Done()
for fn := range taskChan {
result, err := fn(localCtx)
resultsChan <- Result{Result: result, Err: err}
@ -113,7 +115,7 @@ func Run(ctx context.Context, maxConcurrency int, tasks ...Func) ([]Result, erro
}
// Start worker goroutines
for i := 0; i < maxConcurrency; i++ {
for range maxConcurrency {
wg.Add(1)
go runTask()
}
@ -135,8 +137,10 @@ func Run(ctx context.Context, maxConcurrency int, tasks ...Func) ([]Result, erro
for r := range resultsChan {
if r.Err != nil {
cancelCtx()
return nil, r.Err
}
results = append(results, r)
}

@ -33,7 +33,7 @@ func TestService_StackByWebhookID(t *testing.T) {
b := stackBuilder{t: t, store: store}
b.createNewStack(newGuidString(t))
for i := 0; i < 10; i++ {
for range 10 {
b.createNewStack("")
}
webhookID := newGuidString(t)

@ -1,6 +1,7 @@
package images
import (
"cmp"
"strings"
"time"
@ -41,8 +42,7 @@ func (c *RegistryClient) RegistryAuth(image Image) (string, string, error) {
}
func (c *RegistryClient) CertainRegistryAuth(registry *portainer.Registry) (string, string, error) {
err := registryutils.EnsureRegTokenValid(c.dataStore, registry)
if err != nil {
if err := registryutils.EnsureRegTokenValid(c.dataStore, registry); err != nil {
return "", "", err
}
@ -72,8 +72,7 @@ func (c *RegistryClient) EncodedRegistryAuth(image Image) (string, error) {
}
func (c *RegistryClient) EncodedCertainRegistryAuth(registry *portainer.Registry) (string, error) {
err := registryutils.EnsureRegTokenValid(c.dataStore, registry)
if err != nil {
if err := registryutils.EnsureRegTokenValid(c.dataStore, registry); err != nil {
return "", err
}
@ -92,38 +91,32 @@ func findBestMatchRegistry(repository string, registries []portainer.Registry) (
}
var match1, match2, match3 *portainer.Registry
for i := 0; i < len(registries); i++ {
registry := registries[i]
if registry.Type == portainer.DockerHubRegistry {
// try to match repository examples:
// <USERNAME>/nginx:latest
// docker.io/<USERNAME>/nginx:latest
if strings.HasPrefix(repository, registry.Username+"/") || strings.HasPrefix(repository, registry.URL+"/"+registry.Username+"/") {
match1 = &registry
}
// try to match repository examples:
// portainer/portainer-ee:latest
// <NON-USERNAME>/portainer-ee:latest
if match3 == nil {
match3 = &registry
}
}
for _, registry := range registries {
if strings.Contains(repository, registry.URL) {
match2 = &registry
}
}
match := match1
if match == nil {
match = match2
}
if match == nil {
match = match3
if registry.Type != portainer.DockerHubRegistry {
continue
}
// try to match repository examples:
// <USERNAME>/nginx:latest
// docker.io/<USERNAME>/nginx:latest
if strings.HasPrefix(repository, registry.Username+"/") || strings.HasPrefix(repository, registry.URL+"/"+registry.Username+"/") {
match1 = &registry
}
// try to match repository examples:
// portainer/portainer-ee:latest
// <NON-USERNAME>/portainer-ee:latest
if match3 == nil {
match3 = &registry
}
}
match := cmp.Or(match1, match2, match3)
if match == nil {
return nil, errors.New("no registries matched")
}

@ -157,28 +157,33 @@ func Test_customTemplateGitFetch(t *testing.T) {
t.Run("can return the expected file content by multiple calls from one user", func(t *testing.T) {
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
for range 5 {
go func() {
singleAPIRequest(h, jwt1, is, "abcdefg")
wg.Done()
}()
}
wg.Wait()
})
t.Run("can return the expected file content by multiple calls from different users", func(t *testing.T) {
var wg sync.WaitGroup
wg.Add(10)
for i := 0; i < 10; i++ {
for i := range 10 {
go func(j int) {
if j%2 == 0 {
singleAPIRequest(h, jwt1, is, "abcdefg")
} else {
singleAPIRequest(h, jwt2, is, "abcdefg")
}
wg.Done()
}(i)
}
wg.Wait()
})

@ -27,7 +27,7 @@ func TestEndpointDeleteEdgeGroupsConcurrently(t *testing.T) {
var endpointIDs []portainer.EndpointID
for i := 0; i < endpointsCount; i++ {
for i := range endpointsCount {
endpointID := portainer.EndpointID(i) + 1
if err := store.Endpoint().Create(&portainer.Endpoint{

@ -29,7 +29,7 @@ func TestTagDeleteEdgeGroupsConcurrently(t *testing.T) {
var tagIDs []portainer.TagID
for i := 0; i < tagsCount; i++ {
for i := range tagsCount {
tagID := portainer.TagID(i) + 1
if err := store.Tag().Create(&portainer.Tag{

@ -27,7 +27,7 @@ func failFunc(t *testing.T) func() (string, error) {
func TestTokenCacheDataRace(t *testing.T) {
ch := make(chan struct{})
for i := 0; i < 1000; i++ {
for range 1000 {
var tokenCache1, tokenCache2 *tokenCache
mgr := NewTokenCacheManager()

@ -13,7 +13,9 @@ import (
// IsLocalEndpoint returns true if this is a local environment(endpoint)
func IsLocalEndpoint(endpoint *portainer.Endpoint) bool {
return strings.HasPrefix(endpoint.URL, "unix://") || strings.HasPrefix(endpoint.URL, "npipe://") || endpoint.Type == 5
return strings.HasPrefix(endpoint.URL, "unix://") ||
strings.HasPrefix(endpoint.URL, "npipe://") ||
endpoint.Type == portainer.KubernetesLocalEnvironment
}
// IsKubernetesEndpoint returns true if this is a kubernetes environment(endpoint)
@ -61,6 +63,7 @@ func FilterByExcludeIDs(endpoints []portainer.Endpoint, excludeIds []portainer.E
filteredEndpoints = append(filteredEndpoints, endpoint)
}
}
return filteredEndpoints
}
@ -187,12 +190,15 @@ func InitialStorageDetection(endpoint *portainer.Endpoint, endpointService datas
endpoint,
)
}()
log.Info().Msg("attempting to detect storage classes in the cluster")
err := storageDetect(endpoint, endpointService, factory)
if err == nil {
return
}
log.Err(err).Msg("error while detecting storage classes")
go func() {
// Retry after 30 seconds if the initial detection failed.
log.Info().Msg("retrying storage detection in 30 seconds")
@ -203,38 +209,41 @@ func InitialStorageDetection(endpoint *portainer.Endpoint, endpointService datas
}
func UpdateEdgeEndpointHeartbeat(endpoint *portainer.Endpoint, settings *portainer.Settings) {
if IsEdgeEndpoint(endpoint) {
endpoint.QueryDate = time.Now().Unix()
checkInInterval := getEndpointCheckinInterval(endpoint, settings)
endpoint.Heartbeat = endpoint.QueryDate-endpoint.LastCheckInDate <= int64(checkInInterval*2+20)
if !IsEdgeEndpoint(endpoint) {
return
}
endpoint.QueryDate = time.Now().Unix()
checkInInterval := getEndpointCheckinInterval(endpoint, settings)
endpoint.Heartbeat = endpoint.QueryDate-endpoint.LastCheckInDate <= int64(checkInInterval*2+20)
}
func getEndpointCheckinInterval(endpoint *portainer.Endpoint, settings *portainer.Settings) int {
if endpoint.Edge.AsyncMode {
defaultInterval := 60
intervals := [][]int{
{endpoint.Edge.PingInterval, settings.Edge.PingInterval},
{endpoint.Edge.CommandInterval, settings.Edge.CommandInterval},
{endpoint.Edge.SnapshotInterval, settings.Edge.SnapshotInterval},
if !endpoint.Edge.AsyncMode {
if endpoint.EdgeCheckinInterval > 0 {
return endpoint.EdgeCheckinInterval
}
for i := 0; i < len(intervals); i++ {
effectiveInterval := intervals[i][0]
if effectiveInterval <= 0 {
effectiveInterval = intervals[i][1]
}
if effectiveInterval > 0 && effectiveInterval < defaultInterval {
defaultInterval = effectiveInterval
}
}
return settings.EdgeAgentCheckinInterval
}
return defaultInterval
defaultInterval := 60
intervals := [][]int{
{endpoint.Edge.PingInterval, settings.Edge.PingInterval},
{endpoint.Edge.CommandInterval, settings.Edge.CommandInterval},
{endpoint.Edge.SnapshotInterval, settings.Edge.SnapshotInterval},
}
if endpoint.EdgeCheckinInterval > 0 {
return endpoint.EdgeCheckinInterval
for i := range len(intervals) {
effectiveInterval := intervals[i][0]
if effectiveInterval <= 0 {
effectiveInterval = intervals[i][1]
}
if effectiveInterval > 0 && effectiveInterval < defaultInterval {
defaultInterval = effectiveInterval
}
}
return settings.EdgeAgentCheckinInterval
return defaultInterval
}

@ -16,6 +16,8 @@ import (
rbacv1types "k8s.io/client-go/kubernetes/typed/rbac/v1"
)
const maxRetries = 5
// IsRBACEnabled checks if RBAC is enabled in the cluster by creating a service account, then checking it's access to a resourcequota before and after setting a cluster role and cluster role binding
func (kcl *KubeClient) IsRBACEnabled() (bool, error) {
namespace := "default"
@ -23,11 +25,11 @@ func (kcl *KubeClient) IsRBACEnabled() (bool, error) {
resource := "resourcequotas"
saClient := kcl.cli.CoreV1().ServiceAccounts(namespace)
uniqueString := randomstring.RandomString(4) // append a unique string to resource names, incase they already exist
uniqueString := randomstring.RandomString(4) // Append a unique string to resource names, in case they already exist
saName := "portainer-rbac-test-sa-" + uniqueString
err := createServiceAccount(saClient, saName, namespace)
if err != nil {
if err := createServiceAccount(saClient, saName, namespace); err != nil {
log.Error().Err(err).Msg("Error creating service account")
return false, err
}
defer deleteServiceAccount(saClient, saName)
@ -36,29 +38,30 @@ func (kcl *KubeClient) IsRBACEnabled() (bool, error) {
allowed, err := checkServiceAccountAccess(accessReviewClient, saName, verb, resource, namespace)
if err != nil {
log.Error().Err(err).Msg("Error checking service account access")
return false, err
}
// if the service account with no authorizations is allowed, RBAC must be disabled
// If the service account with no authorizations is allowed, RBAC must be disabled
if allowed {
return false, nil
}
// otherwise give the service account an rbac authorisation and check again
// Otherwise give the service account an rbac authorisation and check again
roleClient := kcl.cli.RbacV1().Roles(namespace)
roleName := "portainer-rbac-test-role-" + uniqueString
err = createRole(roleClient, roleName, verb, resource, namespace)
if err != nil {
if err := createRole(roleClient, roleName, verb, resource, namespace); err != nil {
log.Error().Err(err).Msg("Error creating role")
return false, err
}
defer deleteRole(roleClient, roleName)
roleBindingClient := kcl.cli.RbacV1().RoleBindings(namespace)
roleBindingName := "portainer-rbac-test-role-binding-" + uniqueString
err = createRoleBinding(roleBindingClient, roleBindingName, roleName, saName, namespace)
if err != nil {
if err := createRoleBinding(roleBindingClient, roleBindingName, roleName, saName, namespace); err != nil {
log.Error().Err(err).Msg("Error creating role binding")
return false, err
}
defer deleteRoleBinding(roleBindingClient, roleBindingName)
@ -66,10 +69,11 @@ func (kcl *KubeClient) IsRBACEnabled() (bool, error) {
allowed, err = checkServiceAccountAccess(accessReviewClient, saName, verb, resource, namespace)
if err != nil {
log.Error().Err(err).Msg("Error checking service account access with authorizations added")
return false, err
}
// if the service account allowed to list resource quotas after given rbac role, then RBAC is enabled
// If the service account allowed to list resource quotas after given rbac role, then RBAC is enabled
return allowed, nil
}
@ -80,13 +84,13 @@ func createServiceAccount(saClient corev1types.ServiceAccountInterface, name str
Namespace: namespace,
},
}
_, err := saClient.Create(context.Background(), serviceAccount, metav1.CreateOptions{})
return err
}
func deleteServiceAccount(saClient corev1types.ServiceAccountInterface, name string) {
err := saClient.Delete(context.Background(), name, metav1.DeleteOptions{})
if err != nil {
if err := saClient.Delete(context.Background(), name, metav1.DeleteOptions{}); err != nil {
log.Error().Err(err).Msg("Error deleting service account: " + name)
}
}
@ -105,13 +109,13 @@ func createRole(roleClient rbacv1types.RoleInterface, name string, verb string,
},
},
}
_, err := roleClient.Create(context.Background(), role, metav1.CreateOptions{})
return err
}
func deleteRole(roleClient rbacv1types.RoleInterface, name string) {
err := roleClient.Delete(context.Background(), name, metav1.DeleteOptions{})
if err != nil {
if err := roleClient.Delete(context.Background(), name, metav1.DeleteOptions{}); err != nil {
log.Error().Err(err).Msg("Error deleting role: " + name)
}
}
@ -134,17 +138,19 @@ func createRoleBinding(roleBindingClient rbacv1types.RoleBindingInterface, clust
APIGroup: "rbac.authorization.k8s.io",
},
}
roleBinding, err := roleBindingClient.Create(context.Background(), clusterRoleBinding, metav1.CreateOptions{})
if err != nil {
log.Error().Err(err).Msg("Error creating role binding: " + clusterRoleBindingName)
return err
}
// Retry checkRoleBinding a maximum of 5 times with a 100ms wait after each attempt
maxRetries := 5
for i := 0; i < maxRetries; i++ {
for range maxRetries {
err = checkRoleBinding(roleBindingClient, roleBinding.Name)
time.Sleep(100 * time.Millisecond) // Wait for 100ms, even if the check passes
if err == nil {
break
}
@ -154,17 +160,17 @@ func createRoleBinding(roleBindingClient rbacv1types.RoleBindingInterface, clust
}
func checkRoleBinding(roleBindingClient rbacv1types.RoleBindingInterface, name string) error {
_, err := roleBindingClient.Get(context.Background(), name, metav1.GetOptions{})
if err != nil {
if _, err := roleBindingClient.Get(context.Background(), name, metav1.GetOptions{}); err != nil {
log.Error().Err(err).Msg("Error finding rolebinding: " + name)
return err
}
return nil
}
func deleteRoleBinding(roleBindingClient rbacv1types.RoleBindingInterface, name string) {
err := roleBindingClient.Delete(context.Background(), name, metav1.DeleteOptions{})
if err != nil {
if err := roleBindingClient.Delete(context.Background(), name, metav1.DeleteOptions{}); err != nil {
log.Error().Err(err).Msg("Error deleting role binding: " + name)
}
}
@ -183,9 +189,11 @@ func checkServiceAccountAccess(accessReviewClient authv1types.LocalSubjectAccess
User: "system:serviceaccount:default:" + serviceAccountName, // a workaround to be able to use the service account as a user
},
}
result, err := accessReviewClient.Create(context.Background(), subjectAccessReview, metav1.CreateOptions{})
if err != nil {
return false, err
}
return result.Status.Allowed, nil
}

@ -50,13 +50,12 @@ var funcmap = map[StackRemoteOperation]buildCmdFunc{
// build the unpacker cmd for stack based on stackOperation
func (d *stackDeployer) buildUnpackerCmdForStack(stack *portainer.Stack, operation StackRemoteOperation, opts unpackerCmdBuilderOptions) ([]string, error) {
fn := funcmap[operation]
if fn == nil {
return nil, fmt.Errorf("unknown stack operation %s", operation)
}
registriesStrings := getRegistry(opts.registries, d.dataStore)
registriesStrings := generateRegistriesStrings(opts.registries, d.dataStore)
envStrings := getEnv(stack.Env)
return fn(stack, opts, registriesStrings, envStrings), nil
@ -64,72 +63,74 @@ func (d *stackDeployer) buildUnpackerCmdForStack(stack *portainer.Stack, operati
// deploy [-u username -p password] [--skip-tls-verify] [--env KEY1=VALUE1 --env KEY2=VALUE2] <git-repo-url> <ref> <project-name> <destination> <compose-file-path> [<more-file-paths>...]
func buildDeployCmd(stack *portainer.Stack, opts unpackerCmdBuilderOptions, registries []string, env []string) []string {
cmd := []string{}
cmd = append(cmd, UnpackerCmdDeploy)
cmd := []string{UnpackerCmdDeploy}
cmd = appendGitAuthIfNeeded(cmd, stack)
cmd = appendSkipTLSVerifyIfNeeded(cmd, stack)
cmd = append(cmd, env...)
cmd = append(cmd, registries...)
cmd = append(cmd, stack.GitConfig.URL)
cmd = append(cmd, stack.GitConfig.ReferenceName)
cmd = append(cmd, stack.Name)
cmd = append(cmd, opts.composeDestination)
cmd = append(cmd, stack.EntryPoint)
cmd = appendAdditionalFiles(cmd, stack.AdditionalFiles)
return cmd
cmd = append(cmd,
stack.GitConfig.URL,
stack.GitConfig.ReferenceName,
stack.Name,
opts.composeDestination,
stack.EntryPoint,
)
return append(cmd, stack.AdditionalFiles...)
}
// undeploy [-u username -p password] [-k] <git-repo-url> <project-name> <destination> <compose-file-path> [<more-file-paths>...]
func buildUndeployCmd(stack *portainer.Stack, opts unpackerCmdBuilderOptions, registries []string, env []string) []string {
cmd := []string{}
cmd = append(cmd, UnpackerCmdUndeploy)
cmd := []string{UnpackerCmdUndeploy}
cmd = appendGitAuthIfNeeded(cmd, stack)
cmd = append(cmd, stack.GitConfig.URL)
cmd = append(cmd, stack.Name)
cmd = append(cmd, opts.composeDestination)
cmd = append(cmd, stack.EntryPoint)
cmd = appendAdditionalFiles(cmd, stack.AdditionalFiles)
return cmd
cmd = append(cmd, stack.GitConfig.URL,
stack.Name,
opts.composeDestination,
stack.EntryPoint,
)
return append(cmd, stack.AdditionalFiles...)
}
// deploy [-u username -p password] [--skip-tls-verify] [-k] [--env KEY1=VALUE1 --env KEY2=VALUE2] <git-repo-url> <project-name> <destination> <compose-file-path> [<more-file-paths>...]
func buildComposeStartCmd(stack *portainer.Stack, opts unpackerCmdBuilderOptions, registries []string, env []string) []string {
cmd := []string{}
cmd = append(cmd, UnpackerCmdDeploy)
cmd := []string{UnpackerCmdDeploy}
cmd = appendGitAuthIfNeeded(cmd, stack)
cmd = appendSkipTLSVerifyIfNeeded(cmd, stack)
cmd = append(cmd, "-k")
cmd = append(cmd, env...)
cmd = append(cmd, registries...)
cmd = append(cmd, stack.GitConfig.URL)
cmd = append(cmd, stack.GitConfig.ReferenceName)
cmd = append(cmd, stack.Name)
cmd = append(cmd, opts.composeDestination)
cmd = append(cmd, stack.EntryPoint)
cmd = appendAdditionalFiles(cmd, stack.AdditionalFiles)
return cmd
cmd = append(cmd, stack.GitConfig.URL,
stack.GitConfig.ReferenceName,
stack.Name,
opts.composeDestination,
stack.EntryPoint,
)
return append(cmd, stack.AdditionalFiles...)
}
// undeploy [-u username -p password] [-k] <git-repo-url> <project-name> <destination> <compose-file-path> [<more-file-paths>...]
func buildComposeStopCmd(stack *portainer.Stack, opts unpackerCmdBuilderOptions, registries []string, env []string) []string {
cmd := []string{}
cmd = append(cmd, UnpackerCmdUndeploy)
cmd := []string{UnpackerCmdUndeploy}
cmd = appendGitAuthIfNeeded(cmd, stack)
cmd = append(cmd, "-k")
cmd = append(cmd, stack.GitConfig.URL)
cmd = append(cmd, stack.Name)
cmd = append(cmd, opts.composeDestination)
cmd = append(cmd, stack.EntryPoint)
cmd = appendAdditionalFiles(cmd, stack.AdditionalFiles)
return cmd
cmd = append(cmd,
"-k",
stack.GitConfig.URL,
stack.Name,
opts.composeDestination,
stack.EntryPoint,
)
return append(cmd, stack.AdditionalFiles...)
}
// swarm-deploy [-u username -p password] [--skip-tls-verify] [-f] [-r] [--env KEY1=VALUE1 --env KEY2=VALUE2] <git-repo-url> <git-ref> <project-name> <destination> <compose-file-path> [<more-file-paths>...]
func buildSwarmDeployCmd(stack *portainer.Stack, opts unpackerCmdBuilderOptions, registries []string, env []string) []string {
cmd := []string{}
cmd = append(cmd, UnpackerCmdSwarmDeploy)
cmd := []string{UnpackerCmdSwarmDeploy}
cmd = appendGitAuthIfNeeded(cmd, stack)
cmd = appendSkipTLSVerifyIfNeeded(cmd, stack)
if opts.pullImage {
cmd = append(cmd, "-f")
}
@ -137,85 +138,76 @@ func buildSwarmDeployCmd(stack *portainer.Stack, opts unpackerCmdBuilderOptions,
if opts.prune {
cmd = append(cmd, "-r")
}
cmd = append(cmd, env...)
cmd = append(cmd, registries...)
cmd = append(cmd, stack.GitConfig.URL)
cmd = append(cmd, stack.GitConfig.ReferenceName)
cmd = append(cmd, stack.Name)
cmd = append(cmd, opts.composeDestination)
cmd = append(cmd, stack.EntryPoint)
cmd = appendAdditionalFiles(cmd, stack.AdditionalFiles)
return cmd
cmd = append(cmd, stack.GitConfig.URL,
stack.GitConfig.ReferenceName,
stack.Name,
opts.composeDestination,
stack.EntryPoint,
)
return append(cmd, stack.AdditionalFiles...)
}
// swarm-undeploy [-k] <project-name> <destination>
func buildSwarmUndeployCmd(stack *portainer.Stack, opts unpackerCmdBuilderOptions, registries []string, env []string) []string {
cmd := []string{}
cmd = append(cmd, UnpackerCmdSwarmUndeploy)
cmd = append(cmd, stack.Name)
cmd = append(cmd, opts.composeDestination)
return cmd
return []string{UnpackerCmdSwarmUndeploy, stack.Name, opts.composeDestination}
}
// swarm-deploy [-u username -p password] [-f] [-r] [-k] [--skip-tls-verify] [--env KEY1=VALUE1 --env KEY2=VALUE2] <git-repo-url> <project-name> <destination> <compose-file-path> [<more-file-paths>...]
func buildSwarmStartCmd(stack *portainer.Stack, opts unpackerCmdBuilderOptions, registries []string, env []string) []string {
cmd := []string{}
cmd = append(cmd, UnpackerCmdSwarmDeploy, "-f", "-r", "-k")
cmd := []string{UnpackerCmdSwarmDeploy, "-f", "-r", "-k"}
cmd = appendSkipTLSVerifyIfNeeded(cmd, stack)
cmd = append(cmd, getEnv(stack.Env)...)
cmd = append(cmd, registries...)
cmd = append(cmd, stack.GitConfig.URL)
cmd = append(cmd, stack.GitConfig.ReferenceName)
cmd = append(cmd, stack.Name)
cmd = append(cmd, opts.composeDestination)
cmd = append(cmd, stack.EntryPoint)
cmd = appendAdditionalFiles(cmd, stack.AdditionalFiles)
return cmd
cmd = append(cmd, stack.GitConfig.URL,
stack.GitConfig.ReferenceName,
stack.Name,
opts.composeDestination,
stack.EntryPoint,
)
return append(cmd, stack.AdditionalFiles...)
}
// swarm-undeploy [-k] <project-name> <destination>
func buildSwarmStopCmd(stack *portainer.Stack, opts unpackerCmdBuilderOptions, registries []string, env []string) []string {
cmd := []string{}
cmd = append(cmd, UnpackerCmdSwarmUndeploy, "-k")
cmd = append(cmd, stack.Name)
cmd = append(cmd, opts.composeDestination)
return cmd
return []string{UnpackerCmdSwarmUndeploy, "-k", stack.Name, opts.composeDestination}
}
func appendGitAuthIfNeeded(cmd []string, stack *portainer.Stack) []string {
if stack.GitConfig.Authentication != nil && len(stack.GitConfig.Authentication.Password) != 0 {
cmd = append(cmd, "-u", stack.GitConfig.Authentication.Username, "-p", stack.GitConfig.Authentication.Password)
if stack.GitConfig.Authentication == nil || stack.GitConfig.Authentication.Password == "" {
return cmd
}
return cmd
return append(cmd, "-u", stack.GitConfig.Authentication.Username, "-p", stack.GitConfig.Authentication.Password)
}
func appendSkipTLSVerifyIfNeeded(cmd []string, stack *portainer.Stack) []string {
if stack.GitConfig.TLSSkipVerify {
cmd = append(cmd, "--skip-tls-verify")
if !stack.GitConfig.TLSSkipVerify {
return cmd
}
return cmd
}
func appendAdditionalFiles(cmd []string, files []string) []string {
for i := 0; i < len(files); i++ {
cmd = append(cmd, files[i])
}
return cmd
return append(cmd, "--skip-tls-verify")
}
func getRegistry(registries []portainer.Registry, dataStore dataservices.DataStore) []string {
func generateRegistriesStrings(registries []portainer.Registry, dataStore dataservices.DataStore) []string {
cmds := []string{}
for _, registry := range registries {
if registry.Authentication {
err := registryutils.EnsureRegTokenValid(dataStore, &registry)
if err == nil {
username, password, err := registryutils.GetRegEffectiveCredential(&registry)
if err == nil {
cmd := fmt.Sprintf("--registry=%s:%s:%s", username, password, registry.URL)
cmds = append(cmds, cmd)
}
if err := registryutils.EnsureRegTokenValid(dataStore, &registry); err != nil {
continue
}
username, password, err := registryutils.GetRegEffectiveCredential(&registry)
if err != nil {
continue
}
cmds = append(cmds, fmt.Sprintf("--registry=%s:%s:%s", username, password, registry.URL))
}
}

Loading…
Cancel
Save