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

feat(stacks): add the ability to specify env vars when deploying stacks (#1345)

This commit is contained in:
Anthony Lapenna 2017-11-01 10:30:02 +01:00 committed by GitHub
parent 42347d714f
commit 693f1319a4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 173 additions and 30 deletions

View file

@ -2,6 +2,7 @@ package exec
import (
"bytes"
"os"
"os/exec"
"path"
"runtime"
@ -27,7 +28,7 @@ func (manager *StackManager) Login(dockerhub *portainer.DockerHub, registries []
for _, registry := range registries {
if registry.Authentication {
registryArgs := append(args, "login", "--username", registry.Username, "--password", registry.Password, registry.URL)
err := runCommandAndCaptureStdErr(command, registryArgs)
err := runCommandAndCaptureStdErr(command, registryArgs, nil)
if err != nil {
return err
}
@ -36,7 +37,7 @@ func (manager *StackManager) Login(dockerhub *portainer.DockerHub, registries []
if dockerhub.Authentication {
dockerhubArgs := append(args, "login", "--username", dockerhub.Username, "--password", dockerhub.Password)
err := runCommandAndCaptureStdErr(command, dockerhubArgs)
err := runCommandAndCaptureStdErr(command, dockerhubArgs, nil)
if err != nil {
return err
}
@ -49,7 +50,7 @@ func (manager *StackManager) Login(dockerhub *portainer.DockerHub, registries []
func (manager *StackManager) Logout(endpoint *portainer.Endpoint) error {
command, args := prepareDockerCommandAndArgs(manager.binaryPath, endpoint)
args = append(args, "logout")
return runCommandAndCaptureStdErr(command, args)
return runCommandAndCaptureStdErr(command, args, nil)
}
// Deploy executes the docker stack deploy command.
@ -57,21 +58,32 @@ func (manager *StackManager) Deploy(stack *portainer.Stack, endpoint *portainer.
stackFilePath := path.Join(stack.ProjectPath, stack.EntryPoint)
command, args := prepareDockerCommandAndArgs(manager.binaryPath, endpoint)
args = append(args, "stack", "deploy", "--with-registry-auth", "--compose-file", stackFilePath, stack.Name)
return runCommandAndCaptureStdErr(command, args)
env := make([]string, 0)
for _, envvar := range stack.Env {
env = append(env, envvar.Name+"="+envvar.Value)
}
return runCommandAndCaptureStdErr(command, args, env)
}
// Remove executes the docker stack rm command.
func (manager *StackManager) Remove(stack *portainer.Stack, endpoint *portainer.Endpoint) error {
command, args := prepareDockerCommandAndArgs(manager.binaryPath, endpoint)
args = append(args, "stack", "rm", stack.Name)
return runCommandAndCaptureStdErr(command, args)
return runCommandAndCaptureStdErr(command, args, nil)
}
func runCommandAndCaptureStdErr(command string, args []string) error {
func runCommandAndCaptureStdErr(command string, args []string, env []string) error {
var stderr bytes.Buffer
cmd := exec.Command(command, args...)
cmd.Stderr = &stderr
if env != nil {
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, env...)
}
err := cmd.Run()
if err != nil {
return portainer.Error(stderr.String())

View file

@ -62,11 +62,12 @@ func NewStackHandler(bouncer *security.RequestBouncer) *StackHandler {
type (
postStacksRequest struct {
Name string `valid:"required"`
SwarmID string `valid:"required"`
StackFileContent string `valid:""`
GitRepository string `valid:""`
PathInRepository string `valid:""`
Name string `valid:"required"`
SwarmID string `valid:"required"`
StackFileContent string `valid:""`
GitRepository string `valid:""`
PathInRepository string `valid:""`
Env []portainer.Pair `valid:""`
}
postStacksResponse struct {
ID string `json:"Id"`
@ -75,7 +76,8 @@ type (
StackFileContent string `json:"StackFileContent"`
}
putStackRequest struct {
StackFileContent string `valid:"required"`
StackFileContent string `valid:"required"`
Env []portainer.Pair `valid:""`
}
)
@ -165,6 +167,7 @@ func (handler *StackHandler) handlePostStacksStringMethod(w http.ResponseWriter,
Name: stackName,
SwarmID: swarmID,
EntryPoint: file.ComposeFileDefaultName,
Env: req.Env,
}
projectPath, err := handler.FileService.StoreStackFileFromString(string(stack.ID), stackFileContent)
@ -282,6 +285,7 @@ func (handler *StackHandler) handlePostStacksRepositoryMethod(w http.ResponseWri
Name: stackName,
SwarmID: swarmID,
EntryPoint: req.PathInRepository,
Env: req.Env,
}
projectPath := handler.FileService.GetStackProjectPath(string(stack.ID))
@ -369,6 +373,13 @@ func (handler *StackHandler) handlePostStacksFileMethod(w http.ResponseWriter, r
return
}
envParam := r.FormValue("Env")
var env []portainer.Pair
if err = json.Unmarshal([]byte(envParam), &env); err != nil {
httperror.WriteErrorResponse(w, ErrInvalidRequestFormat, http.StatusBadRequest, handler.Logger)
return
}
stackFile, _, err := r.FormFile("file")
if err != nil {
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
@ -394,6 +405,7 @@ func (handler *StackHandler) handlePostStacksFileMethod(w http.ResponseWriter, r
Name: stackName,
SwarmID: swarmID,
EntryPoint: file.ComposeFileDefaultName,
Env: env,
}
projectPath, err := handler.FileService.StoreStackFileFromReader(string(stack.ID), stackFile)
@ -587,6 +599,7 @@ func (handler *StackHandler) handlePutStack(w http.ResponseWriter, r *http.Reque
httperror.WriteErrorResponse(w, ErrInvalidRequestFormat, http.StatusBadRequest, handler.Logger)
return
}
stack.Env = req.Env
_, err = handler.FileService.StoreStackFileFromString(string(stack.ID), req.StackFileContent)
if err != nil {
@ -594,6 +607,12 @@ func (handler *StackHandler) handlePutStack(w http.ResponseWriter, r *http.Reque
return
}
err = handler.StackService.UpdateStack(stack.ID, stack)
if err != nil {
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
return
}
securityContext, err := security.RetrieveRestrictedRequestContext(r)
if err != nil {
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)

View file

@ -138,6 +138,7 @@ type (
EntryPoint string `json:"EntryPoint"`
SwarmID string `json:"SwarmId"`
ProjectPath string
Env []Pair `json:"Env"`
}
// RegistryID represents a registry identifier.