You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
portainer/api/http/handler/stacks/stack_update_git.go

177 lines
7.7 KiB

package stacks
import (
"net/http"
feat(k8s): support git automated sync for k8s applications [EE-577] (#5548) * feat(stack): backport changes to CE EE-1189 * feat(stack): front end backport changes to CE EE-1199 (#5455) * feat(stack): front end backport changes to CE EE-1199 * fix k8s deploy logic * fixed web editor confirmation message typo. EE-1501 * fix(stack): fixed issue auth detail not remembered EE-1502 (#5459) * show status in buttons * removed onChangeRef function. * moved buttons in git form to its own component * removed unused variable. Co-authored-by: ArrisLee <arris_li@hotmail.com> * moved formvalue to kube app component * fix(stack): failed to pull and redeploy compose format k8s stack * fixed form value * fix(k8s): file content overridden when deployment failed with compose format EE-1548 * updated API response to get IsComposeFormat and show appropriate text. * feat(k8s): front end backport to CE * feat(kube): kube app auto update backend (#5547) * error message updates for different file type * not display creation source for external application * added confirmation modal to advanced app created by web editor * stop showing confirmation modal when updating application * disable rollback button when application type is not applicatiom form * only update file after deployment succeded * Revert "only update file after deployment succeded" This reverts commit b94bd2e96f27ca337e9d2fa698da2ab264d9ac86. * fix(k8s): file content overridden when deployment failed with compose format EE-1556 * added analytics-on directive to pull and redeploy button * fix(kube): don't valide resource control access for kube (#5568) * added missing question mark to k8s confirmation modal * fixed webhook format issue * added question marks to k8s app confirmation modal * added space in additional file list. * ignoring error on deletion * fix(k8s): Git authentication info not persisted * added RepositoryMechanismTypes constant * updated analytics functions * covert RepositoryMechanism to constant * fixed typo * removed unused function. * post tech review updates * fixed save settings n redeploy button * refact kub deploy logic * Revert "refact kub deploy logic" This reverts commit cbfdd58eceed438b148c836ed09004dd270d0aa6. * feat(k8s): utilize user token for k8s auto update EE-1594 * feat(k8s): persist kub stack name EE-1630 * feat(k8s): support delete kub stack * fix(app): updated logic to delete stack for different kind apps. (#5648) * fix(app): updated logic to delete stack for different kind apps. * renamed variable * fix import * added StackName field. * fixed stack id not found issue. * fix(k8s): fixed qusetion mark alignment issue in PAT field. (#5611) * fix(k8s): fixed qusetion mark alignment issue in PAT field. * moved inline css to file. * fix(git-form: made auth input text full width * add ignore deleted arg * tech review updates * typo fix * fix(k8s): added console error when deleting k8s service. * fix(console): added no-console config * fix(deploy): added missing service. * fix: use stack editor as an owner when exists (#5678) * fix: tempalte/content based stacks edit/delete * fix(stack): remove stack when no app. (#5769) * fix(stack): remove stack when no app. * support compose format in delete Co-authored-by: ArrisLee <arris_li@hotmail.com> Co-authored-by: Hui <arris_li@hotmail.com> Co-authored-by: fhanportainer <79428273+fhanportainer@users.noreply.github.com> Co-authored-by: Felix Han <felix.han@portainer.io>
3 years ago
"time"
"github.com/asaskevich/govalidator"
feat(k8s): support git automated sync for k8s applications [EE-577] (#5548) * feat(stack): backport changes to CE EE-1189 * feat(stack): front end backport changes to CE EE-1199 (#5455) * feat(stack): front end backport changes to CE EE-1199 * fix k8s deploy logic * fixed web editor confirmation message typo. EE-1501 * fix(stack): fixed issue auth detail not remembered EE-1502 (#5459) * show status in buttons * removed onChangeRef function. * moved buttons in git form to its own component * removed unused variable. Co-authored-by: ArrisLee <arris_li@hotmail.com> * moved formvalue to kube app component * fix(stack): failed to pull and redeploy compose format k8s stack * fixed form value * fix(k8s): file content overridden when deployment failed with compose format EE-1548 * updated API response to get IsComposeFormat and show appropriate text. * feat(k8s): front end backport to CE * feat(kube): kube app auto update backend (#5547) * error message updates for different file type * not display creation source for external application * added confirmation modal to advanced app created by web editor * stop showing confirmation modal when updating application * disable rollback button when application type is not applicatiom form * only update file after deployment succeded * Revert "only update file after deployment succeded" This reverts commit b94bd2e96f27ca337e9d2fa698da2ab264d9ac86. * fix(k8s): file content overridden when deployment failed with compose format EE-1556 * added analytics-on directive to pull and redeploy button * fix(kube): don't valide resource control access for kube (#5568) * added missing question mark to k8s confirmation modal * fixed webhook format issue * added question marks to k8s app confirmation modal * added space in additional file list. * ignoring error on deletion * fix(k8s): Git authentication info not persisted * added RepositoryMechanismTypes constant * updated analytics functions * covert RepositoryMechanism to constant * fixed typo * removed unused function. * post tech review updates * fixed save settings n redeploy button * refact kub deploy logic * Revert "refact kub deploy logic" This reverts commit cbfdd58eceed438b148c836ed09004dd270d0aa6. * feat(k8s): utilize user token for k8s auto update EE-1594 * feat(k8s): persist kub stack name EE-1630 * feat(k8s): support delete kub stack * fix(app): updated logic to delete stack for different kind apps. (#5648) * fix(app): updated logic to delete stack for different kind apps. * renamed variable * fix import * added StackName field. * fixed stack id not found issue. * fix(k8s): fixed qusetion mark alignment issue in PAT field. (#5611) * fix(k8s): fixed qusetion mark alignment issue in PAT field. * moved inline css to file. * fix(git-form: made auth input text full width * add ignore deleted arg * tech review updates * typo fix * fix(k8s): added console error when deleting k8s service. * fix(console): added no-console config * fix(deploy): added missing service. * fix: use stack editor as an owner when exists (#5678) * fix: tempalte/content based stacks edit/delete * fix(stack): remove stack when no app. (#5769) * fix(stack): remove stack when no app. * support compose format in delete Co-authored-by: ArrisLee <arris_li@hotmail.com> Co-authored-by: Hui <arris_li@hotmail.com> Co-authored-by: fhanportainer <79428273+fhanportainer@users.noreply.github.com> Co-authored-by: Felix Han <felix.han@portainer.io>
3 years ago
"github.com/pkg/errors"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
"github.com/portainer/libhttp/response"
portainer "github.com/portainer/portainer/api"
bolterrors "github.com/portainer/portainer/api/bolt/errors"
gittypes "github.com/portainer/portainer/api/git/types"
httperrors "github.com/portainer/portainer/api/http/errors"
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/internal/stackutils"
)
type stackGitUpdatePayload struct {
AutoUpdate *portainer.StackAutoUpdate
Env []portainer.Pair
RepositoryReferenceName string
RepositoryAuthentication bool
RepositoryUsername string
RepositoryPassword string
}
func (payload *stackGitUpdatePayload) Validate(r *http.Request) error {
if govalidator.IsNull(payload.RepositoryReferenceName) {
payload.RepositoryReferenceName = defaultGitReferenceName
}
if err := validateStackAutoUpdate(payload.AutoUpdate); err != nil {
return err
}
return nil
}
// @id StackUpdateGit
feat(kube): advanced apps management [EE-466] (#5446) * feat(stack): backport changes to CE EE-1189 * feat(stack): front end backport changes to CE EE-1199 (#5455) * feat(stack): front end backport changes to CE EE-1199 * fix k8s deploy logic * fixed web editor confirmation message typo. EE-1501 * fix(stack): fixed issue auth detail not remembered EE-1502 (#5459) * show status in buttons * removed onChangeRef function. * moved buttons in git form to its own component * removed unused variable. Co-authored-by: ArrisLee <arris_li@hotmail.com> * moved formvalue to kube app component * fix(stack): failed to pull and redeploy compose format k8s stack * fixed form value * fix(k8s): file content overridden when deployment failed with compose format EE-1548 * updated API response to get IsComposeFormat and show appropriate text. * error message updates for different file type * not display creation source for external application * added confirmation modal to advanced app created by web editor * stop showing confirmation modal when updating application * disable rollback button when application type is not applicatiom form * added analytics-on directive to pull and redeploy button * fix(kube): don't valide resource control access for kube (#5568) * added question marks to k8s app confirmation modal * fix(k8s): Git authentication info not persisted * removed unused function. Co-authored-by: Hui <arris_li@hotmail.com> Co-authored-by: fhanportainer <79428273+fhanportainer@users.noreply.github.com> Co-authored-by: Felix Han <felix.han@portainer.io>
3 years ago
// @summary Update a stack's Git configs
// @description Update the Git settings in a stack, e.g., RepositoryReferenceName and AutoUpdate
// @description **Access policy**: authenticated
// @tags stacks
// @security jwt
// @accept json
// @produce json
// @param id path int true "Stack identifier"
// @param endpointId query int false "Stacks created before version 1.18.0 might not have an associated environment(endpoint) identifier. Use this optional parameter to set the environment(endpoint) identifier used by the stack."
feat(kube): advanced apps management [EE-466] (#5446) * feat(stack): backport changes to CE EE-1189 * feat(stack): front end backport changes to CE EE-1199 (#5455) * feat(stack): front end backport changes to CE EE-1199 * fix k8s deploy logic * fixed web editor confirmation message typo. EE-1501 * fix(stack): fixed issue auth detail not remembered EE-1502 (#5459) * show status in buttons * removed onChangeRef function. * moved buttons in git form to its own component * removed unused variable. Co-authored-by: ArrisLee <arris_li@hotmail.com> * moved formvalue to kube app component * fix(stack): failed to pull and redeploy compose format k8s stack * fixed form value * fix(k8s): file content overridden when deployment failed with compose format EE-1548 * updated API response to get IsComposeFormat and show appropriate text. * error message updates for different file type * not display creation source for external application * added confirmation modal to advanced app created by web editor * stop showing confirmation modal when updating application * disable rollback button when application type is not applicatiom form * added analytics-on directive to pull and redeploy button * fix(kube): don't valide resource control access for kube (#5568) * added question marks to k8s app confirmation modal * fix(k8s): Git authentication info not persisted * removed unused function. Co-authored-by: Hui <arris_li@hotmail.com> Co-authored-by: fhanportainer <79428273+fhanportainer@users.noreply.github.com> Co-authored-by: Felix Han <felix.han@portainer.io>
3 years ago
// @param body body stackGitUpdatePayload true "Git configs for pull and redeploy a stack"
// @success 200 {object} portainer.Stack "Success"
// @failure 400 "Invalid request"
// @failure 403 "Permission denied"
// @failure 404 "Not found"
// @failure 500 "Server error"
// @router /stacks/{id}/git [put]
func (handler *Handler) stackUpdateGit(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
if err != nil {
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid stack identifier route variable", Err: err}
}
var payload stackGitUpdatePayload
err = request.DecodeAndValidateJSONPayload(r, &payload)
if err != nil {
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid request payload", Err: err}
}
stack, err := handler.DataStore.Stack().Stack(portainer.StackID(stackID))
if err == bolterrors.ErrObjectNotFound {
return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "Unable to find a stack with the specified identifier inside the database", Err: err}
} else if err != nil {
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to find a stack with the specified identifier inside the database", Err: err}
} else if stack.GitConfig == nil {
msg := "No Git config in the found stack"
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: msg, Err: errors.New(msg)}
}
// TODO: this is a work-around for stacks created with Portainer version >= 1.17.1
// The EndpointID property is not available for these stacks, this API environment(endpoint)
// can use the optional EndpointID query parameter to associate a valid environment(endpoint) identifier to the stack.
endpointID, err := request.RetrieveNumericQueryParameter(r, "endpointId", true)
if err != nil {
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid query parameter: endpointId", Err: err}
}
if endpointID != int(stack.EndpointID) {
stack.EndpointID = portainer.EndpointID(endpointID)
}
endpoint, err := handler.DataStore.Endpoint().Endpoint(stack.EndpointID)
if err == bolterrors.ErrObjectNotFound {
return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "Unable to find the environment associated to the stack inside the database", Err: err}
} else if err != nil {
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to find the environment associated to the stack inside the database", Err: err}
}
err = handler.requestBouncer.AuthorizedEndpointOperation(r, endpoint)
if err != nil {
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: "Permission denied to access environment", Err: err}
}
feat(k8s): support git automated sync for k8s applications [EE-577] (#5548) * feat(stack): backport changes to CE EE-1189 * feat(stack): front end backport changes to CE EE-1199 (#5455) * feat(stack): front end backport changes to CE EE-1199 * fix k8s deploy logic * fixed web editor confirmation message typo. EE-1501 * fix(stack): fixed issue auth detail not remembered EE-1502 (#5459) * show status in buttons * removed onChangeRef function. * moved buttons in git form to its own component * removed unused variable. Co-authored-by: ArrisLee <arris_li@hotmail.com> * moved formvalue to kube app component * fix(stack): failed to pull and redeploy compose format k8s stack * fixed form value * fix(k8s): file content overridden when deployment failed with compose format EE-1548 * updated API response to get IsComposeFormat and show appropriate text. * feat(k8s): front end backport to CE * feat(kube): kube app auto update backend (#5547) * error message updates for different file type * not display creation source for external application * added confirmation modal to advanced app created by web editor * stop showing confirmation modal when updating application * disable rollback button when application type is not applicatiom form * only update file after deployment succeded * Revert "only update file after deployment succeded" This reverts commit b94bd2e96f27ca337e9d2fa698da2ab264d9ac86. * fix(k8s): file content overridden when deployment failed with compose format EE-1556 * added analytics-on directive to pull and redeploy button * fix(kube): don't valide resource control access for kube (#5568) * added missing question mark to k8s confirmation modal * fixed webhook format issue * added question marks to k8s app confirmation modal * added space in additional file list. * ignoring error on deletion * fix(k8s): Git authentication info not persisted * added RepositoryMechanismTypes constant * updated analytics functions * covert RepositoryMechanism to constant * fixed typo * removed unused function. * post tech review updates * fixed save settings n redeploy button * refact kub deploy logic * Revert "refact kub deploy logic" This reverts commit cbfdd58eceed438b148c836ed09004dd270d0aa6. * feat(k8s): utilize user token for k8s auto update EE-1594 * feat(k8s): persist kub stack name EE-1630 * feat(k8s): support delete kub stack * fix(app): updated logic to delete stack for different kind apps. (#5648) * fix(app): updated logic to delete stack for different kind apps. * renamed variable * fix import * added StackName field. * fixed stack id not found issue. * fix(k8s): fixed qusetion mark alignment issue in PAT field. (#5611) * fix(k8s): fixed qusetion mark alignment issue in PAT field. * moved inline css to file. * fix(git-form: made auth input text full width * add ignore deleted arg * tech review updates * typo fix * fix(k8s): added console error when deleting k8s service. * fix(console): added no-console config * fix(deploy): added missing service. * fix: use stack editor as an owner when exists (#5678) * fix: tempalte/content based stacks edit/delete * fix(stack): remove stack when no app. (#5769) * fix(stack): remove stack when no app. * support compose format in delete Co-authored-by: ArrisLee <arris_li@hotmail.com> Co-authored-by: Hui <arris_li@hotmail.com> Co-authored-by: fhanportainer <79428273+fhanportainer@users.noreply.github.com> Co-authored-by: Felix Han <felix.han@portainer.io>
3 years ago
securityContext, err := security.RetrieveRestrictedRequestContext(r)
if err != nil {
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve info from request context", Err: err}
}
user, err := handler.DataStore.User().User(securityContext.UserID)
if err != nil {
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Cannot find context user", Err: errors.Wrap(err, "failed to fetch the user")}
}
feat(kube): advanced apps management [EE-466] (#5446) * feat(stack): backport changes to CE EE-1189 * feat(stack): front end backport changes to CE EE-1199 (#5455) * feat(stack): front end backport changes to CE EE-1199 * fix k8s deploy logic * fixed web editor confirmation message typo. EE-1501 * fix(stack): fixed issue auth detail not remembered EE-1502 (#5459) * show status in buttons * removed onChangeRef function. * moved buttons in git form to its own component * removed unused variable. Co-authored-by: ArrisLee <arris_li@hotmail.com> * moved formvalue to kube app component * fix(stack): failed to pull and redeploy compose format k8s stack * fixed form value * fix(k8s): file content overridden when deployment failed with compose format EE-1548 * updated API response to get IsComposeFormat and show appropriate text. * error message updates for different file type * not display creation source for external application * added confirmation modal to advanced app created by web editor * stop showing confirmation modal when updating application * disable rollback button when application type is not applicatiom form * added analytics-on directive to pull and redeploy button * fix(kube): don't valide resource control access for kube (#5568) * added question marks to k8s app confirmation modal * fix(k8s): Git authentication info not persisted * removed unused function. Co-authored-by: Hui <arris_li@hotmail.com> Co-authored-by: fhanportainer <79428273+fhanportainer@users.noreply.github.com> Co-authored-by: Felix Han <felix.han@portainer.io>
3 years ago
if stack.Type == portainer.DockerSwarmStack || stack.Type == portainer.DockerComposeStack {
resourceControl, err := handler.DataStore.ResourceControl().ResourceControlByResourceIDAndType(stackutils.ResourceControlID(stack.EndpointID, stack.Name), portainer.StackResourceControl)
if err != nil {
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve a resource control associated to the stack", Err: err}
}
access, err := handler.userCanAccessStack(securityContext, endpoint.ID, resourceControl)
if err != nil {
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to verify user authorizations to validate stack access", Err: err}
}
if !access {
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: "Access denied to resource", Err: httperrors.ErrResourceAccessDenied}
}
}
//stop the autoupdate job if there is any
if stack.AutoUpdate != nil {
stopAutoupdate(stack.ID, stack.AutoUpdate.JobID, *handler.Scheduler)
}
//update retrieved stack data based on the payload
stack.GitConfig.ReferenceName = payload.RepositoryReferenceName
stack.AutoUpdate = payload.AutoUpdate
stack.Env = payload.Env
feat(k8s): support git automated sync for k8s applications [EE-577] (#5548) * feat(stack): backport changes to CE EE-1189 * feat(stack): front end backport changes to CE EE-1199 (#5455) * feat(stack): front end backport changes to CE EE-1199 * fix k8s deploy logic * fixed web editor confirmation message typo. EE-1501 * fix(stack): fixed issue auth detail not remembered EE-1502 (#5459) * show status in buttons * removed onChangeRef function. * moved buttons in git form to its own component * removed unused variable. Co-authored-by: ArrisLee <arris_li@hotmail.com> * moved formvalue to kube app component * fix(stack): failed to pull and redeploy compose format k8s stack * fixed form value * fix(k8s): file content overridden when deployment failed with compose format EE-1548 * updated API response to get IsComposeFormat and show appropriate text. * feat(k8s): front end backport to CE * feat(kube): kube app auto update backend (#5547) * error message updates for different file type * not display creation source for external application * added confirmation modal to advanced app created by web editor * stop showing confirmation modal when updating application * disable rollback button when application type is not applicatiom form * only update file after deployment succeded * Revert "only update file after deployment succeded" This reverts commit b94bd2e96f27ca337e9d2fa698da2ab264d9ac86. * fix(k8s): file content overridden when deployment failed with compose format EE-1556 * added analytics-on directive to pull and redeploy button * fix(kube): don't valide resource control access for kube (#5568) * added missing question mark to k8s confirmation modal * fixed webhook format issue * added question marks to k8s app confirmation modal * added space in additional file list. * ignoring error on deletion * fix(k8s): Git authentication info not persisted * added RepositoryMechanismTypes constant * updated analytics functions * covert RepositoryMechanism to constant * fixed typo * removed unused function. * post tech review updates * fixed save settings n redeploy button * refact kub deploy logic * Revert "refact kub deploy logic" This reverts commit cbfdd58eceed438b148c836ed09004dd270d0aa6. * feat(k8s): utilize user token for k8s auto update EE-1594 * feat(k8s): persist kub stack name EE-1630 * feat(k8s): support delete kub stack * fix(app): updated logic to delete stack for different kind apps. (#5648) * fix(app): updated logic to delete stack for different kind apps. * renamed variable * fix import * added StackName field. * fixed stack id not found issue. * fix(k8s): fixed qusetion mark alignment issue in PAT field. (#5611) * fix(k8s): fixed qusetion mark alignment issue in PAT field. * moved inline css to file. * fix(git-form: made auth input text full width * add ignore deleted arg * tech review updates * typo fix * fix(k8s): added console error when deleting k8s service. * fix(console): added no-console config * fix(deploy): added missing service. * fix: use stack editor as an owner when exists (#5678) * fix: tempalte/content based stacks edit/delete * fix(stack): remove stack when no app. (#5769) * fix(stack): remove stack when no app. * support compose format in delete Co-authored-by: ArrisLee <arris_li@hotmail.com> Co-authored-by: Hui <arris_li@hotmail.com> Co-authored-by: fhanportainer <79428273+fhanportainer@users.noreply.github.com> Co-authored-by: Felix Han <felix.han@portainer.io>
3 years ago
stack.UpdatedBy = user.Username
stack.UpdateDate = time.Now().Unix()
stack.GitConfig.Authentication = nil
if payload.RepositoryAuthentication {
password := payload.RepositoryPassword
if password == "" && stack.GitConfig != nil && stack.GitConfig.Authentication != nil {
password = stack.GitConfig.Authentication.Password
}
stack.GitConfig.Authentication = &gittypes.GitAuthentication{
Username: payload.RepositoryUsername,
Password: password,
}
_, err = handler.GitService.LatestCommitID(stack.GitConfig.URL, stack.GitConfig.ReferenceName, stack.GitConfig.Authentication.Username, stack.GitConfig.Authentication.Password)
if err != nil {
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to fetch git repository", Err: err}
}
}
if payload.AutoUpdate != nil && payload.AutoUpdate.Interval != "" {
jobID, e := startAutoupdate(stack.ID, stack.AutoUpdate.Interval, handler.Scheduler, handler.StackDeployer, handler.DataStore, handler.GitService)
if e != nil {
return e
}
stack.AutoUpdate.JobID = jobID
}
//save the updated stack to DB
err = handler.DataStore.Stack().UpdateStack(stack.ID, stack)
if err != nil {
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to persist the stack changes inside the database", Err: err}
}
if stack.GitConfig != nil && stack.GitConfig.Authentication != nil && stack.GitConfig.Authentication.Password != "" {
// sanitize password in the http response to minimise possible security leaks
stack.GitConfig.Authentication.Password = ""
}
return response.JSON(w, stack)
}