Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/command/up/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ func (p *Plural) handleUp(c *cli.Context) error {
}

ctx, err := up.Build(c.Bool("cloud"))
ctx.IgnorePreflights(c.Bool("ignore-preflights") || c.Bool("dry-run"))
if err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ require (
github.com/posthog/posthog-go v1.4.10
github.com/samber/lo v1.52.0
github.com/urfave/cli v1.22.16
github.com/whilp/git-urls v1.0.0
github.com/yuin/gopher-lua v1.1.1
gitlab.com/gitlab-org/api/client-go v0.128.0
golang.org/x/crypto v0.48.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,8 @@ github.com/vmihailenco/msgpack/v4 v4.3.13 h1:A2wsiTbvp63ilDaWmsk2wjx6xZdxQOvpiNl
github.com/vmihailenco/msgpack/v4 v4.3.13/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc=
github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/whilp/git-urls v1.0.0 h1:95f6UMWN5FKW71ECsXRUd3FVYiXdrE7aX4NZKcPmIjU=
github.com/whilp/git-urls v1.0.0/go.mod h1:J16SAmobsqc3Qcy98brfl5f5+e0clUvg1krgwk/qCfE=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
Expand Down
2 changes: 1 addition & 1 deletion pkg/client/plural.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func (p *Plural) HandleInitWithProject(c *cli.Context) (*manifest.ProjectManifes
repo := ""
p.InitPluralClient()

git, err := wkspace.Preflight(c.Bool("dry-run"))
git, err := wkspace.Preflight(c.Bool("dry-run"), c.Bool("ignore-preflights"))
if err != nil && (git || c.Bool("dry-run")) {
return nil, err
}
Expand Down
85 changes: 58 additions & 27 deletions pkg/up/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"
"path/filepath"
"regexp"
"strings"

"github.com/AlecAivazis/survey/v2"
Expand All @@ -17,19 +18,21 @@ import (
"github.com/pluralsh/plural-cli/pkg/utils/git"

"github.com/mitchellh/go-homedir"
giturls "github.com/whilp/git-urls"
)

type Context struct {
Provider providerapi.Provider
Manifest *manifest.ProjectManifest
Config *config.Config
Cloud bool
RepoUrl string
StacksIdentity string
Delims *delims
ImportCluster *string
CloudCluster string
dir string
Provider providerapi.Provider
Manifest *manifest.ProjectManifest
Config *config.Config
Cloud bool
RepoUrl string
StacksIdentity string
Delims *delims
ImportCluster *string
CloudCluster string
dir string
ignorePreflights bool
}

type delims struct {
Expand All @@ -50,23 +53,27 @@ func (ctx *Context) changeDelims() {
ctx.Delims = &delims{"[[", "]]"}
}

func (ctx *Context) IgnorePreflights(ignore bool) {
ctx.ignorePreflights = ignore
}

func (ctx *Context) SetImportCluster(id string) {
ctx.ImportCluster = lo.ToPtr(id)
}

func (ctx *Context) Backfill() error {
context, err := manifest.FetchContext()
if err != nil {
return backfillConsoleContext(ctx.Manifest)
return ctx.backfillConsoleContext(ctx.Manifest)
}

console, ok := context.Configuration["console"]
if !ok {
return backfillConsoleContext(ctx.Manifest)
return ctx.backfillConsoleContext(ctx.Manifest)
}

if _, ok = console["private_key"]; !ok {
return backfillConsoleContext(ctx.Manifest)
return ctx.backfillConsoleContext(ctx.Manifest)
}

if v, ok := console["repo_url"]; ok {
Expand Down Expand Up @@ -103,7 +110,7 @@ func Build(cloud bool) (*Context, error) {
}, nil
}

func backfillConsoleContext(_ *manifest.ProjectManifest) error {
func (context *Context) backfillConsoleContext(_ *manifest.ProjectManifest) error {
path := manifest.ContextPath()
ctx, err := manifest.FetchContext()
if err != nil {
Expand All @@ -115,7 +122,17 @@ func backfillConsoleContext(_ *manifest.ProjectManifest) error {
console = map[string]interface{}{}
}

utils.Highlight("It looks like you cloned this repo before running plural up, we just need you to generate and give us a deploy key to continue\n")
utils.Highlight("It looks like you cloned this repo before running plural up, we just need to ensure authentication is setup correctly to continue\n")

url, err := git.GetURL()
if err != nil {
return err
}

if strings.HasPrefix(url, "http") {
return fmt.Errorf("found non-ssh upstream url %s, please reclone the repo with SSH and retry", url)
}

utils.Highlight("If you want, you can use `plural crypto ssh-keygen` to generate a keypair to use as a deploy key as well\n\n")

files, err := filepath.Glob(filepath.Join(os.Getenv("HOME"), ".ssh", "*"))
Expand Down Expand Up @@ -144,17 +161,10 @@ func backfillConsoleContext(_ *manifest.ProjectManifest) error {
return err
}

url, err := git.GetURL()
if err != nil {
return err
}

if strings.HasPrefix(url, "http") {
return fmt.Errorf("found non-ssh upstream url %s, please reclone the repo with SSH and retry", url)
}

if err := verifySSHKey(contents, url); err != nil {
return fmt.Errorf("ssh key not valid for url %s, error: %w", url, err)
if !context.ignorePreflights {
if err := verifySSHKey(contents, url); err != nil {
return fmt.Errorf("ssh key not valid for url %s, error: %w. If you want to bypass this check, you can use the --ignore-preflights flag", url, err)
}
}

console["repo_url"] = url
Expand All @@ -174,9 +184,30 @@ func verifySSHKey(key, url string) error {
return
}
}(dir)
auth, _ := git.SSHAuth("git", key, "")

auth, _ := git.SSHAuth(getGitUsername(url), key, "")
if _, err := git.Clone(auth, url, dir); err != nil {
return err
}
return nil
}

var (
scpSyntax = regexp.MustCompile(`^([a-zA-Z0-9-._~]+@)?([a-zA-Z0-9._-]+):([a-zA-Z0-9./._-]+)(?:\?||$)(.*)$`)
)

func getGitUsername(url string) string {
match := scpSyntax.FindAllStringSubmatch(url, -1)
if len(match) > 0 {
if match[0][1] != "" {
return strings.TrimRight(match[0][1], "@")
}
}

uname := "git"
parsedUrl, err := giturls.Parse(url)
if err == nil {
uname = parsedUrl.User.Username()
}
return uname
}
44 changes: 44 additions & 0 deletions pkg/up/context_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package up

import "testing"

func TestGetGitUsername(t *testing.T) {
tests := []struct {
name string
url string
want string
}{
{
name: "github scp-style",
url: "git@github.com:acme-corp/widget-service.git",
want: "git",
},
{
name: "github ssh transport",
url: "ssh://git@github.com/acme-corp/widget-service.git",
want: "git",
},
{
name: "gitlab nested group",
url: "git@gitlab.com:engineering/platform/api-gateway.git",
want: "git",
},
{
name: "azure devops ssh (v3 path)",
url: "my-org@ssh.dev.azure.com:v3/MyOrg/MyProject/MyRepo",
want: "my-org",
},
{
name: "bitbucket cloud workspace repo",
url: "another-org@bitbucket.org:acme-workspace/mobile-app.git",
want: "another-org",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := getGitUsername(tt.url); got != tt.want {
t.Errorf("getGitUsername(%q) = %q, want %q", tt.url, got, tt.want)
}
})
}
}
4 changes: 2 additions & 2 deletions pkg/wkspace/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/pluralsh/plural-cli/pkg/utils/git"
)

func Preflight(dryRun bool) (bool, error) {
func Preflight(dryRun, ignorePreflights bool) (bool, error) {
requirements := []string{"terraform", "git"}
if dryRun {
requirements = []string{"git"}
Expand All @@ -24,7 +24,7 @@ func Preflight(dryRun bool) (bool, error) {
}
}

if !dryRun {
if !dryRun && !ignorePreflights {
fmt.Print("\nTesting if git ssh is properly configured...")
if err := checkGitSSH(); err != nil {
fmt.Printf("%s\n\n", err.Error())
Expand Down
Loading