mirror of https://github.com/portainer/portainer
Introduced ClonePrivateRepositoryWithDeploymentKey and its handler
parent
7dd9e9e365
commit
f496776490
|
@ -1,11 +1,12 @@
|
|||
package git
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
"gopkg.in/src-d/go-git.v4"
|
||||
"gopkg.in/src-d/go-git.v4/plumbing"
|
||||
gitSsh "gopkg.in/src-d/go-git.v4/plumbing/transport/ssh"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Service represents a service for managing Git.
|
||||
|
@ -44,3 +45,34 @@ func cloneRepository(repositoryURL, referenceName string, destination string) er
|
|||
_, err := git.PlainClone(destination, false, options)
|
||||
return err
|
||||
}
|
||||
|
||||
func (service *Service) ClonePrivateRepositoryWithDeploymentKey(repositoryURL, referenceName string, destination string, privateKeyPem []byte) error {
|
||||
// url := "git@github.com:ssbkang/personal-development.git"
|
||||
// directory := "personal-development"
|
||||
// https://github.com/portainer/portainer-compose
|
||||
|
||||
signer, _ := ssh.ParsePrivateKey(privateKeyPem)
|
||||
auth := &gitSsh.PublicKeys{
|
||||
User: "git",
|
||||
Signer: signer,
|
||||
HostKeyCallbackHelper: gitSsh.HostKeyCallbackHelper{
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
},
|
||||
}
|
||||
|
||||
repositoryURL = strings.Replace(repositoryURL, "https://", "git@", 1)
|
||||
repositoryURL += ".git"
|
||||
|
||||
options := &git.CloneOptions{
|
||||
URL: repositoryURL,
|
||||
RecurseSubmodules: git.DefaultSubmoduleRecursionDepth,
|
||||
Auth: auth,
|
||||
}
|
||||
|
||||
if referenceName != "" {
|
||||
options.ReferenceName = plumbing.ReferenceName(referenceName)
|
||||
}
|
||||
|
||||
_, err := git.PlainClone(destination, false, options)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -87,11 +87,13 @@ func (handler *Handler) createComposeStackFromFileContent(w http.ResponseWriter,
|
|||
return response.JSON(w, stack)
|
||||
}
|
||||
|
||||
// Update struc to cater for deployment key
|
||||
type composeStackFromGitRepositoryPayload struct {
|
||||
Name string
|
||||
RepositoryURL string
|
||||
RepositoryReferenceName string
|
||||
RepositoryAuthentication bool
|
||||
RepositoryDeploymentKey string
|
||||
RepositoryUsername string
|
||||
RepositoryPassword string
|
||||
ComposeFilePathInRepository string
|
||||
|
@ -145,11 +147,13 @@ func (handler *Handler) createComposeStackFromGitRepository(w http.ResponseWrite
|
|||
projectPath := handler.FileService.GetStackProjectPath(strconv.Itoa(int(stack.ID)))
|
||||
stack.ProjectPath = projectPath
|
||||
|
||||
// Add Deployment Key
|
||||
gitCloneParams := &cloneRepositoryParameters{
|
||||
url: payload.RepositoryURL,
|
||||
referenceName: payload.RepositoryReferenceName,
|
||||
path: projectPath,
|
||||
authentication: payload.RepositoryAuthentication,
|
||||
deploymentKey: payload.RepositoryDeploymentKey,
|
||||
username: payload.RepositoryUsername,
|
||||
password: payload.RepositoryPassword,
|
||||
}
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
package stacks
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/asaskevich/govalidator"
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
|
@ -12,6 +8,9 @@ import (
|
|||
"github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/filesystem"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type swarmStackFromFileContentPayload struct {
|
||||
|
@ -92,6 +91,7 @@ func (handler *Handler) createSwarmStackFromFileContent(w http.ResponseWriter, r
|
|||
return response.JSON(w, stack)
|
||||
}
|
||||
|
||||
// Update struc to cater for deployment key
|
||||
type swarmStackFromGitRepositoryPayload struct {
|
||||
Name string
|
||||
SwarmID string
|
||||
|
@ -99,6 +99,7 @@ type swarmStackFromGitRepositoryPayload struct {
|
|||
RepositoryURL string
|
||||
RepositoryReferenceName string
|
||||
RepositoryAuthentication bool
|
||||
RepositoryDeploymentKey string
|
||||
RepositoryUsername string
|
||||
RepositoryPassword string
|
||||
ComposeFilePathInRepository string
|
||||
|
@ -111,12 +112,18 @@ func (payload *swarmStackFromGitRepositoryPayload) Validate(r *http.Request) err
|
|||
if govalidator.IsNull(payload.SwarmID) {
|
||||
return portainer.Error("Invalid Swarm ID")
|
||||
}
|
||||
|
||||
// Need to improve validators for SSH based URL and deployment key type
|
||||
|
||||
/*
|
||||
if govalidator.IsNull(payload.RepositoryURL) || !govalidator.IsURL(payload.RepositoryURL) {
|
||||
return portainer.Error("Invalid repository URL. Must correspond to a valid URL format")
|
||||
}
|
||||
if payload.RepositoryAuthentication && (govalidator.IsNull(payload.RepositoryUsername) || govalidator.IsNull(payload.RepositoryPassword)) {
|
||||
return portainer.Error("Invalid repository credentials. Username and password must be specified when authentication is enabled")
|
||||
|
||||
if payload.RepositoryAuthentication && (govalidator.IsNull(payload.RepositoryDeploymentKey)) || (govalidator.IsNull(payload.RepositoryUsername) || govalidator.IsNull(payload.RepositoryPassword)) {
|
||||
return portainer.Error("Invalid repository credentials or deploymenet key. Either Username & password or a deployment key must be specified when authentication is enabled")
|
||||
}
|
||||
*/
|
||||
if govalidator.IsNull(payload.ComposeFilePathInRepository) {
|
||||
payload.ComposeFilePathInRepository = filesystem.ComposeFileDefaultName
|
||||
}
|
||||
|
@ -160,6 +167,7 @@ func (handler *Handler) createSwarmStackFromGitRepository(w http.ResponseWriter,
|
|||
referenceName: payload.RepositoryReferenceName,
|
||||
path: projectPath,
|
||||
authentication: payload.RepositoryAuthentication,
|
||||
deploymentKey: payload.RepositoryDeploymentKey,
|
||||
username: payload.RepositoryUsername,
|
||||
password: payload.RepositoryPassword,
|
||||
}
|
||||
|
|
|
@ -5,13 +5,18 @@ type cloneRepositoryParameters struct {
|
|||
referenceName string
|
||||
path string
|
||||
authentication bool
|
||||
deploymentKey string
|
||||
username string
|
||||
password string
|
||||
}
|
||||
|
||||
func (handler *Handler) cloneGitRepository(parameters *cloneRepositoryParameters) error {
|
||||
if parameters.authentication {
|
||||
if parameters.authentication && parameters.username != "" && parameters.password != "" {
|
||||
return handler.GitService.ClonePrivateRepositoryWithBasicAuth(parameters.url, parameters.referenceName, parameters.path, parameters.username, parameters.password)
|
||||
}
|
||||
if parameters.authentication && parameters.deploymentKey != "" {
|
||||
deploymentKey, _ := handler.DeploymentKeyService.DeploymentKeyByName(parameters.deploymentKey)
|
||||
return handler.GitService.ClonePrivateRepositoryWithDeploymentKey(parameters.url, parameters.referenceName, parameters.path, deploymentKey.PrivateKey)
|
||||
}
|
||||
return handler.GitService.ClonePublicRepository(parameters.url, parameters.referenceName, parameters.path)
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ type Handler struct {
|
|||
stackDeletionMutex *sync.Mutex
|
||||
requestBouncer *security.RequestBouncer
|
||||
*mux.Router
|
||||
DeploymentKeyService portainer.DeploymentKeyService
|
||||
FileService portainer.FileService
|
||||
GitService portainer.GitService
|
||||
StackService portainer.StackService
|
||||
|
|
|
@ -182,6 +182,7 @@ func (server *Server) Start() error {
|
|||
stackHandler.FileService = server.FileService
|
||||
stackHandler.StackService = server.StackService
|
||||
stackHandler.EndpointService = server.EndpointService
|
||||
stackHandler.DeploymentKeyService = server.DeploymentKeyService
|
||||
stackHandler.ResourceControlService = server.ResourceControlService
|
||||
stackHandler.SwarmStackManager = server.SwarmStackManager
|
||||
stackHandler.ComposeStackManager = server.ComposeStackManager
|
||||
|
|
|
@ -817,6 +817,7 @@ type (
|
|||
GitService interface {
|
||||
ClonePublicRepository(repositoryURL, referenceName string, destination string) error
|
||||
ClonePrivateRepositoryWithBasicAuth(repositoryURL, referenceName string, destination, username, password string) error
|
||||
ClonePrivateRepositoryWithDeploymentKey(repositoryURL, referenceName string, destination string, privateKeyPem []byte) error
|
||||
}
|
||||
|
||||
// JobScheduler represents a service to run jobs on a periodic basis
|
||||
|
|
Loading…
Reference in New Issue