diff --git a/api/exec/compose_stack.go b/api/exec/compose_stack.go index 45c2846d3..360e6dc7a 100644 --- a/api/exec/compose_stack.go +++ b/api/exec/compose_stack.go @@ -70,6 +70,7 @@ func (manager *ComposeStackManager) Up(ctx context.Context, stack *portainer.Sta }, ForceRecreate: options.ForceRecreate, AbortOnContainerExit: options.AbortOnContainerExit, + RemoveOrphans: options.Prune, }) return errors.Wrap(err, "failed to deploy a stack") } diff --git a/api/http/handler/stacks/stack_migrate.go b/api/http/handler/stacks/stack_migrate.go index a3774b7e9..0907d9635 100644 --- a/api/http/handler/stacks/stack_migrate.go +++ b/api/http/handler/stacks/stack_migrate.go @@ -199,6 +199,7 @@ func (handler *Handler) migrateComposeStack(r *http.Request, stack *portainer.St handler.DataStore, handler.FileService, handler.StackDeployer, + true, false, false) if err != nil { diff --git a/api/http/handler/stacks/stack_update.go b/api/http/handler/stacks/stack_update.go index ee2fe0761..24b07692f 100644 --- a/api/http/handler/stacks/stack_update.go +++ b/api/http/handler/stacks/stack_update.go @@ -26,6 +26,8 @@ type updateComposeStackPayload struct { Env []portainer.Pair // RepullImageAndRedeploy indicates whether to force repulling images and redeploying the stack RepullImageAndRedeploy bool + // Prune services that are no longer referenced + Prune bool `example:"true"` // Deprecated(2.36): use RepullImageAndRedeploy instead for cleaner responsibility // Force a pulling to current image with the original tag though the image is already the latest @@ -45,7 +47,7 @@ type updateSwarmStackPayload struct { StackFileContent string `example:"version: 3\n services:\n web:\n image:nginx"` // A list of environment(endpoint) variables used during stack deployment Env []portainer.Pair - // Prune services that are no longer referenced (only available for Swarm stacks) + // Prune services that are no longer referenced Prune bool `example:"true"` // RepullImageAndRedeploy indicates whether to force repulling images and redeploying the stack RepullImageAndRedeploy bool @@ -242,6 +244,7 @@ func (handler *Handler) updateComposeStack(tx dataservices.DataStoreTx, r *http. endpoint, handler.FileService, handler.StackDeployer, + payload.Prune, payload.RepullImageAndRedeploy, payload.RepullImageAndRedeploy) if err != nil { @@ -252,6 +255,14 @@ func (handler *Handler) updateComposeStack(tx dataservices.DataStoreTx, r *http. return httperror.InternalServerError(err.Error(), err) } + if stack.Option != nil { + stack.Option.Prune = payload.Prune + } else { + stack.Option = &portainer.StackOption{ + Prune: payload.Prune, + } + } + // Deploy the stack if err := composeDeploymentConfig.Deploy(); err != nil { if rollbackErr := handler.FileService.RollbackStackFile(stackFolder, stack.EntryPoint); rollbackErr != nil { diff --git a/api/http/handler/stacks/stack_update_git_redeploy.go b/api/http/handler/stacks/stack_update_git_redeploy.go index a8b09b9d3..a543a1b42 100644 --- a/api/http/handler/stacks/stack_update_git_redeploy.go +++ b/api/http/handler/stacks/stack_update_git_redeploy.go @@ -130,8 +130,11 @@ func (handler *Handler) stackGitRedeploy(w http.ResponseWriter, r *http.Request) payload.RepullImageAndRedeploy = payload.RepullImageAndRedeploy || payload.PullImage stack.GitConfig.ReferenceName = payload.RepositoryReferenceName stack.Env = payload.Env - if stack.Type == portainer.DockerSwarmStack { - stack.Option = &portainer.StackOption{Prune: payload.Prune} + if stack.Type == portainer.DockerSwarmStack || stack.Type == portainer.DockerComposeStack { + if stack.Option == nil { + stack.Option = &portainer.StackOption{} + } + stack.Option.Prune = payload.Prune } if stack.Type == portainer.KubernetesStack { @@ -233,7 +236,9 @@ func (handler *Handler) deployStack(r *http.Request, stack *portainer.Stack, pul return httperror.InternalServerError("Unable to retrieve info from request context", err) } - deploymentConfiger, err = deployments.CreateComposeStackDeploymentConfig(securityContext, stack, endpoint, handler.DataStore, handler.FileService, handler.StackDeployer, pullImage, true) + prune := stack.Option != nil && stack.Option.Prune + + deploymentConfiger, err = deployments.CreateComposeStackDeploymentConfig(securityContext, stack, endpoint, handler.DataStore, handler.FileService, handler.StackDeployer, prune, pullImage, true) if err != nil { return httperror.InternalServerError(err.Error(), err) } diff --git a/api/http/handler/stacks/stack_update_test.go b/api/http/handler/stacks/stack_update_test.go index c4665b7c0..a0e5af04a 100644 --- a/api/http/handler/stacks/stack_update_test.go +++ b/api/http/handler/stacks/stack_update_test.go @@ -16,7 +16,6 @@ import ( "github.com/portainer/portainer/api/datastore" "github.com/portainer/portainer/api/filesystem" "github.com/portainer/portainer/api/internal/testhelpers" - "github.com/portainer/portainer/api/stacks/deployments" "github.com/portainer/portainer/api/stacks/stackutils" "github.com/portainer/portainer/pkg/fips" httperror "github.com/portainer/portainer/pkg/libhttp/error" @@ -248,7 +247,7 @@ func TestStackUpdate(t *testing.T) { handler := NewHandler(testhelpers.NewTestRequestBouncer()) handler.DataStore = store handler.FileService = fileService - handler.StackDeployer = testStackDeployer{} + handler.StackDeployer = testhelpers.NewTestStackDeployer() handler.ComposeStackManager = testhelpers.NewComposeStackManager() handler.SwarmStackManager = swarmStackManager{} @@ -318,7 +317,11 @@ type updateStackInTxTestSetup struct { req *http.Request } -func setupUpdateStackInTxTest(t *testing.T, stack *portainer.Stack, payload *updateComposeStackPayload) *updateStackInTxTestSetup { +type testUpdateStackPayload interface { + *updateComposeStackPayload | *updateSwarmStackPayload +} + +func setupUpdateStackInTxTest[T testUpdateStackPayload](t *testing.T, stack *portainer.Stack, payload T) *updateStackInTxTestSetup { t.Helper() _, store := datastore.MustNewTestStore(t, true, true) @@ -364,7 +367,7 @@ func setupUpdateStackInTxTest(t *testing.T, stack *portainer.Stack, payload *upd handler := NewHandler(testhelpers.NewTestRequestBouncer()) handler.DataStore = store handler.FileService = fileService - handler.StackDeployer = testStackDeployer{} + handler.StackDeployer = testhelpers.NewTestStackDeployer() handler.ComposeStackManager = testhelpers.NewComposeStackManager() // Create mock request with security context @@ -398,22 +401,73 @@ func (manager swarmStackManager) NormalizeStackName(name string) string { return name } -type testStackDeployer struct { - deployments.StackDeployer +func Test_updateSwarmStack_Prune(t *testing.T) { + fips.InitFIPS(false) + + payload := &updateSwarmStackPayload{ + StackFileContent: "version: '3'\nservices:\n web:\n image: nginx:latest", + Prune: true, + } + stack := &portainer.Stack{ + ID: 1, + Name: "test-stack-prune", + EntryPoint: "docker-compose.yml", + Type: portainer.DockerSwarmStack, + } + setup := setupUpdateStackInTxTest(t, stack, payload) + setup.handler.SwarmStackManager = swarmStackManager{} + deployer := testhelpers.NewTestStackDeployer() + setup.handler.StackDeployer = deployer + + err := setup.store.UpdateTx(func(tx dataservices.DataStoreTx) error { + _, handlerErr := setup.handler.updateStackInTx(tx, setup.req, setup.stack.ID, setup.endpoint.ID) + if handlerErr != nil { + return handlerErr + } + return nil + }) + require.NoError(t, err, "handler should accept Prune=true and succeed") + + stored, err := setup.store.Stack().Read(setup.stack.ID) + require.NoError(t, err) + require.NotNil(t, stored.Option, "stack.Option should not be nil") + assert.True(t, stored.Option.Prune, "stack.Option.Prune should be persisted as true") + + assert.Equal(t, 1, deployer.DeploySwarmCallCount, "DeploySwarmStack should be called exactly once") + assert.True(t, deployer.LastPrune, "deployer should be invoked with prune=true") } -func (testStackDeployer) DeployComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, forcePullImage, forceRecreate bool) error { - return nil -} +func Test_updateComposeStack_Prune(t *testing.T) { + fips.InitFIPS(false) -func (testStackDeployer) DeploySwarmStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, prune, pullImage bool) error { - return nil -} + payload := &updateComposeStackPayload{ + StackFileContent: "version: '3'\nservices:\n web:\n image: nginx:latest", + Prune: true, + } + stack := &portainer.Stack{ + ID: 1, + Name: "test-stack-prune", + EntryPoint: "docker-compose.yml", + Type: portainer.DockerComposeStack, + } + setup := setupUpdateStackInTxTest(t, stack, payload) + deployer := testhelpers.NewTestStackDeployer() + setup.handler.StackDeployer = deployer -func (testStackDeployer) DeployRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, forcePullImage, forceRecreate bool) error { - return nil -} + err := setup.store.UpdateTx(func(tx dataservices.DataStoreTx) error { + _, handlerErr := setup.handler.updateStackInTx(tx, setup.req, setup.stack.ID, setup.endpoint.ID) + if handlerErr != nil { + return handlerErr + } + return nil + }) + require.NoError(t, err, "handler should accept Prune=true and succeed") -func (testStackDeployer) DeployRemoteSwarmStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, prune, pullImage bool) error { - return nil + stored, err := setup.store.Stack().Read(setup.stack.ID) + require.NoError(t, err) + require.NotNil(t, stored.Option, "stack.Option should not be nil") + assert.True(t, stored.Option.Prune, "stack.Option.Prune should be persisted as true") + + assert.Equal(t, 1, deployer.DeployComposeCallCount, "DeployComposeStack should be called exactly once") + assert.True(t, deployer.LastPrune, "deployer should be invoked with prune=true") } diff --git a/api/internal/testhelpers/stack_deployer.go b/api/internal/testhelpers/stack_deployer.go new file mode 100644 index 000000000..788d105a4 --- /dev/null +++ b/api/internal/testhelpers/stack_deployer.go @@ -0,0 +1,61 @@ +package testhelpers + +import portainer "github.com/portainer/portainer/api" + +type TestStackDeployer struct { + DeployComposeCallCount int + DeploySwarmCallCount int + LastPrune bool +} + +func NewTestStackDeployer() *TestStackDeployer { + return &TestStackDeployer{} +} + +func (d *TestStackDeployer) DeployComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, prune, forcePullImage, forceRecreate bool) error { + d.DeployComposeCallCount++ + d.LastPrune = prune + return nil +} + +func (d *TestStackDeployer) DeploySwarmStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, prune, pullImage bool) error { + d.DeploySwarmCallCount++ + d.LastPrune = prune + return nil +} + +func (d *TestStackDeployer) DeployKubernetesStack(stack *portainer.Stack, endpoint *portainer.Endpoint, user *portainer.User) error { + return nil +} + +func (d *TestStackDeployer) DeployRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, prune, forcePullImage, forceRecreate bool) error { + return nil +} + +func (d *TestStackDeployer) UndeployRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint) error { + return nil +} + +func (d *TestStackDeployer) StartRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry) error { + return nil +} + +func (d *TestStackDeployer) StopRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint) error { + return nil +} + +func (d *TestStackDeployer) DeployRemoteSwarmStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, prune, pullImage bool) error { + return nil +} + +func (d *TestStackDeployer) UndeployRemoteSwarmStack(stack *portainer.Stack, endpoint *portainer.Endpoint) error { + return nil +} + +func (d *TestStackDeployer) StartRemoteSwarmStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry) error { + return nil +} + +func (d *TestStackDeployer) StopRemoteSwarmStack(stack *portainer.Stack, endpoint *portainer.Endpoint) error { + return nil +} diff --git a/api/stacks/deployments/compose_unpacker_cmd_builder.go b/api/stacks/deployments/compose_unpacker_cmd_builder.go index 6d51c4500..e7b7e6222 100644 --- a/api/stacks/deployments/compose_unpacker_cmd_builder.go +++ b/api/stacks/deployments/compose_unpacker_cmd_builder.go @@ -62,12 +62,17 @@ func (d *stackDeployer) buildUnpackerCmdForStack(stack *portainer.Stack, operati return fn(stack, opts, registriesStrings, envStrings), nil } -// deploy [-u username -p password] [--skip-tls-verify] [--force-recreate] [-k] [--env KEY1=VALUE1 --env KEY2=VALUE2] [...] +// deploy [-u username -p password] [--skip-tls-verify] [--force-recreate] [-r] [-k] [--env KEY1=VALUE1 --env KEY2=VALUE2] [...] func buildDeployCmd(stack *portainer.Stack, opts unpackerCmdBuilderOptions, registries []string, env []string) []string { cmd := []string{UnpackerCmdDeploy} cmd = appendGitAuthIfNeeded(cmd, stack) cmd = appendSkipTLSVerifyIfNeeded(cmd, stack) cmd = appendForceRecreateIfNeeded(cmd, opts.forceRecreate) + + if opts.prune { + cmd = append(cmd, "-r") + } + cmd = append(cmd, env...) cmd = append(cmd, registries...) cmd = append(cmd, diff --git a/api/stacks/deployments/deploy.go b/api/stacks/deployments/deploy.go index 1512cde53..d63c3362d 100644 --- a/api/stacks/deployments/deploy.go +++ b/api/stacks/deployments/deploy.go @@ -159,9 +159,9 @@ func redeployWhenChangedSecondStage( switch stack.Type { case portainer.DockerComposeStack: if stackutils.IsRelativePathStack(stack) { - err = deployer.DeployRemoteComposeStack(stack, endpoint, registries, true, false) + err = deployer.DeployRemoteComposeStack(stack, endpoint, registries, true, true, false) } else { - err = deployer.DeployComposeStack(stack, endpoint, registries, true, false) + err = deployer.DeployComposeStack(stack, endpoint, registries, true, true, false) } if err != nil { diff --git a/api/stacks/deployments/deploy_test.go b/api/stacks/deployments/deploy_test.go index 2163a91c8..4eb147931 100644 --- a/api/stacks/deployments/deploy_test.go +++ b/api/stacks/deployments/deploy_test.go @@ -82,7 +82,7 @@ func (s noopDeployer) DeploySwarmStack(stack *portainer.Stack, endpoint *portain return nil } -func (s noopDeployer) DeployComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, forcePullImage, forceRecreate bool) error { +func (s noopDeployer) DeployComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, prune, forcePullImage, forceRecreate bool) error { return nil } @@ -91,7 +91,7 @@ func (s noopDeployer) DeployKubernetesStack(stack *portainer.Stack, endpoint *po } // with unpacker -func (s noopDeployer) DeployRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, forcePullImage, forceRecreate bool) error { +func (s noopDeployer) DeployRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, prune, forcePullImage, forceRecreate bool) error { return nil } func (s noopDeployer) UndeployRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint) error { diff --git a/api/stacks/deployments/deployer.go b/api/stacks/deployments/deployer.go index 862ee9526..f4733d587 100644 --- a/api/stacks/deployments/deployer.go +++ b/api/stacks/deployments/deployer.go @@ -15,7 +15,7 @@ import ( type BaseStackDeployer interface { DeploySwarmStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, prune, pullImage bool) error - DeployComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, forcePullImage, forceRecreate bool) error + DeployComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, prune, forcePullImage, forceRecreate bool) error DeployKubernetesStack(stack *portainer.Stack, endpoint *portainer.Endpoint, user *portainer.User) error } @@ -61,7 +61,7 @@ func (d *stackDeployer) DeploySwarmStack(stack *portainer.Stack, endpoint *porta return d.swarmStackManager.Deploy(stack, prune, pullImage, endpoint) } -func (d *stackDeployer) DeployComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, forcePullImage, forceRecreate bool) error { +func (d *stackDeployer) DeployComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, prune, forcePullImage, forceRecreate bool) error { d.lock.Lock() defer d.lock.Unlock() @@ -77,6 +77,7 @@ func (d *stackDeployer) DeployComposeStack(stack *portainer.Stack, endpoint *por return d.composeStackManager.Up(context.TODO(), stack, endpoint, portainer.ComposeUpOptions{ ComposeOptions: options, ForceRecreate: forceRecreate, + Prune: prune, }) } diff --git a/api/stacks/deployments/deployer_remote.go b/api/stacks/deployments/deployer_remote.go index 34fd3148a..1dd931325 100644 --- a/api/stacks/deployments/deployer_remote.go +++ b/api/stacks/deployments/deployer_remote.go @@ -34,7 +34,7 @@ const ( type RemoteStackDeployer interface { // compose - DeployRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, forcePullImage bool, forceRecreate bool) error + DeployRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, prune bool, forcePullImage bool, forceRecreate bool) error UndeployRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint) error StartRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry) error StopRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint) error @@ -50,6 +50,7 @@ func (d *stackDeployer) DeployRemoteComposeStack( stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, + prune bool, forcePullImage bool, forceRecreate bool, ) error { @@ -72,6 +73,7 @@ func (d *stackDeployer) DeployRemoteComposeStack( unpackerCmdBuilderOptions{ forceRecreate: forceRecreate, registries: registries, + prune: prune, }, ) } diff --git a/api/stacks/deployments/deployment_compose_config.go b/api/stacks/deployments/deployment_compose_config.go index b51497d14..c23a557e6 100644 --- a/api/stacks/deployments/deployment_compose_config.go +++ b/api/stacks/deployments/deployment_compose_config.go @@ -22,16 +22,17 @@ type ComposeStackDeploymentConfig struct { ForceCreate bool FileService portainer.FileService StackDeployer StackDeployer + prune bool } -func CreateComposeStackDeploymentConfig(securityContext *security.RestrictedRequestContext, stack *portainer.Stack, endpoint *portainer.Endpoint, dataStore dataservices.DataStore, fileService portainer.FileService, deployer StackDeployer, forcePullImage, forceCreate bool) (*ComposeStackDeploymentConfig, error) { - return CreateComposeStackDeploymentConfigTx(dataStore, securityContext, stack, endpoint, fileService, deployer, forcePullImage, forceCreate) +func CreateComposeStackDeploymentConfig(securityContext *security.RestrictedRequestContext, stack *portainer.Stack, endpoint *portainer.Endpoint, dataStore dataservices.DataStore, fileService portainer.FileService, deployer StackDeployer, prune, forcePullImage, forceCreate bool) (*ComposeStackDeploymentConfig, error) { + return CreateComposeStackDeploymentConfigTx(dataStore, securityContext, stack, endpoint, fileService, deployer, prune, forcePullImage, forceCreate) } // Alternate function that works within a transaction // We didn't update the original function to use a transaction because it would be a breaking change for many other files. // Let's do this only where necessary for now. This is also planed to be refactored in the future, but not prioritized right now. -func CreateComposeStackDeploymentConfigTx(tx dataservices.DataStoreTx, securityContext *security.RestrictedRequestContext, stack *portainer.Stack, endpoint *portainer.Endpoint, fileService portainer.FileService, deployer StackDeployer, forcePullImage, forceCreate bool) (*ComposeStackDeploymentConfig, error) { +func CreateComposeStackDeploymentConfigTx(tx dataservices.DataStoreTx, securityContext *security.RestrictedRequestContext, stack *portainer.Stack, endpoint *portainer.Endpoint, fileService portainer.FileService, deployer StackDeployer, prune, forcePullImage, forceCreate bool) (*ComposeStackDeploymentConfig, error) { user, err := tx.User().Read(securityContext.UserID) if err != nil { return nil, fmt.Errorf("unable to load user information from the database: %w", err) @@ -48,6 +49,7 @@ func CreateComposeStackDeploymentConfigTx(tx dataservices.DataStoreTx, securityC stack: stack, endpoint: endpoint, registries: filteredRegistries, + prune: prune, isAdmin: securityContext.IsAdmin, user: user, forcePullImage: forcePullImage, @@ -86,10 +88,10 @@ func (config *ComposeStackDeploymentConfig) Deploy() error { } if stackutils.IsRelativePathStack(config.stack) { - return config.StackDeployer.DeployRemoteComposeStack(config.stack, config.endpoint, config.registries, config.forcePullImage, config.ForceCreate) + return config.StackDeployer.DeployRemoteComposeStack(config.stack, config.endpoint, config.registries, config.prune, config.forcePullImage, config.ForceCreate) } - return config.StackDeployer.DeployComposeStack(config.stack, config.endpoint, config.registries, config.forcePullImage, config.ForceCreate) + return config.StackDeployer.DeployComposeStack(config.stack, config.endpoint, config.registries, config.prune, config.forcePullImage, config.ForceCreate) } func (config *ComposeStackDeploymentConfig) GetResponse() string { diff --git a/api/stacks/stackbuilders/compose_file_content_builder.go b/api/stacks/stackbuilders/compose_file_content_builder.go index 796631611..980ec9057 100644 --- a/api/stacks/stackbuilders/compose_file_content_builder.go +++ b/api/stacks/stackbuilders/compose_file_content_builder.go @@ -68,7 +68,7 @@ func (b *ComposeStackFileContentBuilder) Deploy(payload *StackPayload, endpoint return b } - composeDeploymentConfig, err := deployments.CreateComposeStackDeploymentConfig(b.SecurityContext, b.stack, endpoint, b.dataStore, b.fileService, b.stackDeployer, false, false) + composeDeploymentConfig, err := deployments.CreateComposeStackDeploymentConfig(b.SecurityContext, b.stack, endpoint, b.dataStore, b.fileService, b.stackDeployer, false, false, false) if err != nil { b.err = err return b diff --git a/api/stacks/stackbuilders/compose_file_upload_builder.go b/api/stacks/stackbuilders/compose_file_upload_builder.go index 608e12024..9921d0a80 100644 --- a/api/stacks/stackbuilders/compose_file_upload_builder.go +++ b/api/stacks/stackbuilders/compose_file_upload_builder.go @@ -58,7 +58,7 @@ func (b *ComposeStackFileUploadBuilder) Deploy(payload *StackPayload, endpoint * return b } - composeDeploymentConfig, err := deployments.CreateComposeStackDeploymentConfig(b.SecurityContext, b.stack, endpoint, b.dataStore, b.fileService, b.stackDeployer, false, false) + composeDeploymentConfig, err := deployments.CreateComposeStackDeploymentConfig(b.SecurityContext, b.stack, endpoint, b.dataStore, b.fileService, b.stackDeployer, false, false, false) if err != nil { b.err = err return b diff --git a/api/stacks/stackbuilders/compose_git_builder.go b/api/stacks/stackbuilders/compose_git_builder.go index 0b2d1590b..5088b6d29 100644 --- a/api/stacks/stackbuilders/compose_git_builder.go +++ b/api/stacks/stackbuilders/compose_git_builder.go @@ -58,7 +58,7 @@ func (b *ComposeStackGitBuilder) Deploy(payload *StackPayload, endpoint *portain return b } - composeDeploymentConfig, err := deployments.CreateComposeStackDeploymentConfig(b.SecurityContext, b.stack, endpoint, b.dataStore, b.fileService, b.stackDeployer, false, false) + composeDeploymentConfig, err := deployments.CreateComposeStackDeploymentConfig(b.SecurityContext, b.stack, endpoint, b.dataStore, b.fileService, b.stackDeployer, false, false, false) if err != nil { b.err = err return b