Add support for cloning private repos as part of automation API (#5333)

This commit is contained in:
Paul Stack 2020-09-14 20:24:57 +01:00 committed by GitHub
parent 0504780346
commit aafe84d823
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 129 additions and 1 deletions

View file

@ -9,6 +9,11 @@ CHANGELOG
asking interactively as the final option.
[#5327](https://github.com/pulumi/pulumi/pull/5327)
- feat(autoapi): Add support for working with private Git repos. Either `SSHPrivateKeyPath`,
`PersonalAccessToken` or `UserName` and `Password` can be pushed to the `auto.GitRepo` struct
when interacting with a private repo
[#5333](https://github.com/pulumi/pulumi/pull/5333)
## 2.10.0 (2020-09-10)
- feat(autoapi): add Upsert methods for stacks

View file

@ -18,6 +18,7 @@ package auto
import (
"context"
"fmt"
"os"
"os/exec"
"path/filepath"
@ -205,6 +206,63 @@ func ExampleGitRepo() {
NewStackRemoteSource(ctx, fqsn, repo, Project(project))
}
func ExampleGitRepo_personalAccessToken() {
ctx := context.Background()
pName := "go_remote_proj"
fqsn := FullyQualifiedStackName("myOrg", pName, "myStack")
// Get the Sourcecode Repository PERSONAL_ACCESS_TOKEN
token, _ := os.LookupEnv("PERSONAL_ACCESS_TOKEN")
repo := GitRepo{
URL: "https://github.com/pulumi/test-repo.git",
ProjectPath: "goproj",
Auth: &GitAuth{
PersonalAccessToken: token,
},
}
// initialize a stack from the git repo, specifying our project override
NewStackRemoteSource(ctx, fqsn, repo)
}
func ExampleGitRepo_privateKeyPath() {
ctx := context.Background()
pName := "go_remote_proj"
fqsn := FullyQualifiedStackName("myOrg", pName, "myStack")
repo := GitRepo{
URL: "https://github.com/pulumi/test-repo.git",
ProjectPath: "goproj",
Auth: &GitAuth{
SSHPrivateKeyPath: "/Users/myuser/.ssh/id_rsa",
Password: "PrivateKeyPassword",
},
}
// initialize a stack from the git repo, specifying our project override
NewStackRemoteSource(ctx, fqsn, repo)
}
func ExampleGitRepo_usernameAndPassword() {
ctx := context.Background()
pName := "go_remote_proj"
fqsn := FullyQualifiedStackName("myOrg", pName, "myStack")
repo := GitRepo{
URL: "https://github.com/pulumi/test-repo.git",
ProjectPath: "goproj",
Auth: &GitAuth{
// This will use a username and password combination for the private repo
Username: "myuser",
Password: "myPassword1234!",
},
}
// initialize a stack from the git repo, specifying our project override
NewStackRemoteSource(ctx, fqsn, repo)
}
func ExampleLocalWorkspace() {
ctx := context.Background()
// create a workspace from a local project

View file

@ -21,11 +21,57 @@ import (
"github.com/pkg/errors"
git "gopkg.in/src-d/go-git.v4"
"gopkg.in/src-d/go-git.v4/plumbing"
"gopkg.in/src-d/go-git.v4/plumbing/transport/http"
"gopkg.in/src-d/go-git.v4/plumbing/transport/ssh"
)
func setupGitRepo(ctx context.Context, workDir string, repoArgs *GitRepo) (string, error) {
cloneOptions := &git.CloneOptions{
URL: repoArgs.URL,
}
if repoArgs.Auth != nil {
authDetails := repoArgs.Auth
// Each of the authentication options are mutually exclusive so let's check that only 1 is specified
if (authDetails.SSHPrivateKeyPath != "" && authDetails.PersonalAccessToken != "") ||
(authDetails.SSHPrivateKeyPath != "" && authDetails.Username != "") ||
(authDetails.PersonalAccessToken != "" && authDetails.Username != "") {
return "", errors.New("please specify one authentication option of `Personal Access Token`, " +
"`Username\\Password` or `SSH Private Key Path`")
}
// Firstly we will try to check that an SSH Private Key Path has been specified
if authDetails.SSHPrivateKeyPath != "" {
publicKeys, err := ssh.NewPublicKeysFromFile("git", repoArgs.Auth.SSHPrivateKeyPath, repoArgs.Auth.Password)
if err != nil {
return "", errors.Wrap(err, "unable to use SSH Private Key")
}
cloneOptions.Auth = publicKeys
}
// Then we check to see if a Personal Access Token has been specified
// the username for use with a PAT can be *anything* but an empty string
// so we are setting this to `git`
if authDetails.PersonalAccessToken != "" {
cloneOptions.Auth = &http.BasicAuth{
Username: "git",
Password: repoArgs.Auth.PersonalAccessToken,
}
}
// then we check to see if a username and a password has been specified
if authDetails.Password != "" && authDetails.Username != "" {
cloneOptions.Auth = &http.BasicAuth{
Username: repoArgs.Auth.Username,
Password: repoArgs.Auth.Password,
}
}
}
// clone
repo, err := git.PlainCloneContext(ctx, workDir, false, &git.CloneOptions{URL: repoArgs.URL})
repo, err := git.PlainCloneContext(ctx, workDir, false, cloneOptions)
if err != nil {
return "", errors.Wrap(err, "unable to clone repo")
}

View file

@ -584,6 +584,25 @@ type GitRepo struct {
CommitHash string
// Optional function to execute after enlisting in the specified repo.
Setup SetupFn
// GitAuth is the different Authentication options for the Git repository
Auth *GitAuth
}
// GitAuth is the authentication details that can be specified for a private Git repo.
// There are 3 different authentication paths:
// * PersonalAccessToken
// * SSHPrivateKeyPath (and it's potential password)
// * Username and Password
// Only 1 authentication path is valid. If more than 1 is specified it will result in an error
type GitAuth struct {
// The absolute path to a private key for access to the git repo
SSHPrivateKeyPath string
// The password that pairs with a username or as part of an SSH Private Key
Password string
// PersonalAccessToken is a Git personal access token in replacement of your password
PersonalAccessToken string
// Username is the username to use when authenticating to a git repository
Username string
}
// SetupFn is a function to execute after enlisting in a git repo.