mirror of https://github.com/portainer/portainer
chore(code): use int ranges in loops BE-10990 (#12028)
parent
468c12c75b
commit
31bdb948a8
|
@ -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 = ®istry
|
||||
}
|
||||
|
||||
// try to match repository examples:
|
||||
// portainer/portainer-ee:latest
|
||||
// <NON-USERNAME>/portainer-ee:latest
|
||||
if match3 == nil {
|
||||
match3 = ®istry
|
||||
}
|
||||
}
|
||||
|
||||
for _, registry := range registries {
|
||||
if strings.Contains(repository, registry.URL) {
|
||||
match2 = ®istry
|
||||
}
|
||||
|
||||
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 = ®istry
|
||||
}
|
||||
|
||||
// try to match repository examples:
|
||||
// portainer/portainer-ee:latest
|
||||
// <NON-USERNAME>/portainer-ee:latest
|
||||
if match3 == nil {
|
||||
match3 = ®istry
|
||||
}
|
||||
}
|
||||
|
||||
match := match1
|
||||
if match == nil {
|
||||
match = match2
|
||||
}
|
||||
if match == nil {
|
||||
match = match3
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
defaultInterval := 60
|
||||
intervals := [][]int{
|
||||
{endpoint.Edge.PingInterval, settings.Edge.PingInterval},
|
||||
{endpoint.Edge.CommandInterval, settings.Edge.CommandInterval},
|
||||
{endpoint.Edge.SnapshotInterval, settings.Edge.SnapshotInterval},
|
||||
}
|
||||
|
||||
for i := range len(intervals) {
|
||||
effectiveInterval := intervals[i][0]
|
||||
if effectiveInterval <= 0 {
|
||||
effectiveInterval = intervals[i][1]
|
||||
}
|
||||
|
||||
return defaultInterval
|
||||
if effectiveInterval > 0 && effectiveInterval < defaultInterval {
|
||||
defaultInterval = effectiveInterval
|
||||
}
|
||||
}
|
||||
|
||||
if endpoint.EdgeCheckinInterval > 0 {
|
||||
return endpoint.EdgeCheckinInterval
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
return append(cmd, "--skip-tls-verify")
|
||||
}
|
||||
|
||||
func appendAdditionalFiles(cmd []string, files []string) []string {
|
||||
for i := 0; i < len(files); i++ {
|
||||
cmd = append(cmd, files[i])
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
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, ®istry)
|
||||
if err == nil {
|
||||
username, password, err := registryutils.GetRegEffectiveCredential(®istry)
|
||||
if err == nil {
|
||||
cmd := fmt.Sprintf("--registry=%s:%s:%s", username, password, registry.URL)
|
||||
cmds = append(cmds, cmd)
|
||||
}
|
||||
if err := registryutils.EnsureRegTokenValid(dataStore, ®istry); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
username, password, err := registryutils.GetRegEffectiveCredential(®istry)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
cmds = append(cmds, fmt.Sprintf("--registry=%s:%s:%s", username, password, registry.URL))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue