From fdd14455de161707bc3f33045bb1febb954a5658 Mon Sep 17 00:00:00 2001 From: roi-codefresh <60569147+roi-codefresh@users.noreply.github.com> Date: Tue, 8 Jun 2021 12:00:04 +0300 Subject: [PATCH] fix local application infer (#88) --- cmd/commands/app.go | 47 +++++++++++++++++++++------------- cmd/commands/project.go | 6 ++--- cmd/commands/repo.go | 9 +++---- pkg/application/application.go | 25 ++++++++++++------ pkg/git/repository.go | 14 +++++++--- pkg/git/repository_test.go | 2 +- 6 files changed, 64 insertions(+), 39 deletions(-) diff --git a/cmd/commands/app.go b/cmd/commands/app.go index 3df106c2..4106c0e7 100644 --- a/cmd/commands/app.go +++ b/cmd/commands/app.go @@ -17,15 +17,16 @@ import ( argocdv1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" "github.com/go-git/go-billy/v5/memfs" + "github.com/go-git/go-billy/v5/osfs" billyUtils "github.com/go-git/go-billy/v5/util" "github.com/spf13/cobra" ) type ( AppCreateOptions struct { - CloneOpts *git.CloneOptions - ProjectName string - AppOpts *application.CreateOptions + CloneOpts *git.CloneOptions + ProjectName string + AppOpts *application.CreateOptions } AppDeleteOptions struct { @@ -48,9 +49,6 @@ func NewAppCommand() *cobra.Command { Use: "application", Aliases: []string{"app"}, Short: "Manage applications", - PersistentPreRun: func(_ *cobra.Command, _ []string) { - cloneOpts.Parse() - }, Run: func(cmd *cobra.Command, args []string) { cmd.HelpFunc()(cmd, args) exit(1) @@ -67,8 +65,8 @@ func NewAppCommand() *cobra.Command { func NewAppCreateCommand(cloneOpts *git.CloneOptions) *cobra.Command { var ( - appOpts *application.CreateOptions - projectName string + appOpts *application.CreateOptions + projectName string ) cmd := &cobra.Command{ @@ -92,6 +90,7 @@ func NewAppCreateCommand(cloneOpts *git.CloneOptions) *cobra.Command { app create --app github.com/some_org/some_repo/manifests?ref=v1.2.3 --project project_name `), + PreRun: func(cmd *cobra.Command, args []string) { cloneOpts.Parse() }, RunE: func(cmd *cobra.Command, args []string) error { if len(args) < 1 { log.G().Fatal("must enter application name") @@ -99,9 +98,9 @@ func NewAppCreateCommand(cloneOpts *git.CloneOptions) *cobra.Command { appOpts.AppName = args[0] return RunAppCreate(cmd.Context(), &AppCreateOptions{ - CloneOpts: cloneOpts, - ProjectName: projectName, - AppOpts: appOpts, + CloneOpts: cloneOpts, + ProjectName: projectName, + AppOpts: appOpts, }) }, } @@ -162,23 +161,33 @@ func setAppOptsDefaults(ctx context.Context, repofs fs.FS, opts *AppCreateOption opts.AppOpts.DestNamespace = "default" } - if opts.AppOpts.AppType == "" { - log.G().Infof("Cloning app from %s to infer App Type", opts.AppOpts.AppSpecifier) + if opts.AppOpts.AppType != "" { + return nil + } + + var fsys fs.FS + if _, err := os.Stat(opts.AppOpts.AppSpecifier); err == nil { + // local directory + fsys = fs.Create(osfs.New(opts.AppOpts.AppSpecifier)) + } else { + host, orgRepo, p, _, _, _, _ := util.ParseGitUrl(opts.AppOpts.AppSpecifier) + url := host + orgRepo + log.G().Infof("cloning repo: '%s', to infer app type from path '%s'", url, p) cloneOpts := &git.CloneOptions{ Repo: opts.AppOpts.AppSpecifier, Auth: opts.CloneOpts.Auth, - FS: memfs.New(), + FS: fs.Create(memfs.New()), } cloneOpts.Parse() - _, fs, err := clone(ctx, cloneOpts) + _, fsys, err = clone(ctx, cloneOpts) if err != nil { return err } - - opts.AppOpts.AppType = application.InferAppType(fs) - log.G().Infof("Inferred AppType: %s", opts.AppOpts.AppType) } + opts.AppOpts.AppType = application.InferAppType(fsys) + log.G().Infof("inferred application type: %s", opts.AppOpts.AppType) + return nil } @@ -220,6 +229,7 @@ func NewAppListCommand(cloneOpts *git.CloneOptions) *cobra.Command { app list `), + PreRun: func(cmd *cobra.Command, args []string) { cloneOpts.Parse() }, RunE: func(cmd *cobra.Command, args []string) error { if len(args) < 1 { log.G().Fatal("must enter a project name") @@ -303,6 +313,7 @@ func NewAppDeleteCommand(cloneOpts *git.CloneOptions) *cobra.Command { app delete --project `), + PreRun: func(cmd *cobra.Command, args []string) { cloneOpts.Parse() }, RunE: func(cmd *cobra.Command, args []string) error { if len(args) < 1 { log.G().Fatal("must enter application name") diff --git a/cmd/commands/project.go b/cmd/commands/project.go index 2aa28b54..2151aa4b 100644 --- a/cmd/commands/project.go +++ b/cmd/commands/project.go @@ -65,9 +65,6 @@ func NewProjectCommand() *cobra.Command { Use: "project", Aliases: []string{"proj"}, Short: "Manage projects", - PersistentPreRun: func(_ *cobra.Command, _ []string) { - cloneOpts.Parse() - }, Run: func(cmd *cobra.Command, args []string) { cmd.HelpFunc()(cmd, args) exit(1) @@ -107,6 +104,7 @@ func NewProjectCreateCommand(cloneOpts *git.CloneOptions) *cobra.Command { project create `), + PreRun: func(cmd *cobra.Command, args []string) { cloneOpts.Parse() }, RunE: func(cmd *cobra.Command, args []string) error { if len(args) < 1 { log.G().Fatal("must enter project name") @@ -341,6 +339,7 @@ func NewProjectListCommand(cloneOpts *git.CloneOptions) *cobra.Command { project list `), + PreRun: func(cmd *cobra.Command, args []string) { cloneOpts.Parse() }, RunE: func(cmd *cobra.Command, args []string) error { return RunProjectList(cmd.Context(), &ProjectListOptions{ CloneOpts: cloneOpts, @@ -408,6 +407,7 @@ func NewProjectDeleteCommand(cloneOpts *git.CloneOptions) *cobra.Command { project delete `), + PreRun: func(cmd *cobra.Command, args []string) { cloneOpts.Parse() }, RunE: func(cmd *cobra.Command, args []string) error { if len(args) < 1 { log.G().Fatal("must enter project name") diff --git a/cmd/commands/repo.go b/cmd/commands/repo.go index 168dbb20..682a6207 100644 --- a/cmd/commands/repo.go +++ b/cmd/commands/repo.go @@ -165,9 +165,8 @@ func NewRepoBootstrapCommand() *cobra.Command { repo bootstrap --repo https://github.com/example/repo/path/to/installation_root `), - PersistentPreRun: func(_ *cobra.Command, _ []string) { - cloneOpts.Parse() - }, RunE: func(cmd *cobra.Command, args []string) error { + PreRun: func(cmd *cobra.Command, args []string) { cloneOpts.Parse() }, + RunE: func(cmd *cobra.Command, args []string) error { return RunRepoBootstrap(cmd.Context(), &RepoBootstrapOptions{ AppSpecifier: appSpecifier, InstallationMode: installationMode, @@ -260,7 +259,7 @@ func RunRepoCreate(ctx context.Context, opts *RepoCreateOptions) (*git.CloneOpti co := &git.CloneOptions{ Repo: repoUrl, - FS: memfs.New(), + FS: fs.Create(memfs.New()), Auth: git.Auth{ Password: opts.Token, }, @@ -306,7 +305,7 @@ func RunRepoBootstrap(ctx context.Context, opts *RepoBootstrapOptions) error { return nil } - log.G().Infof("cloning repo: %s", opts.CloneOptions.URL) + log.G().Infof("cloning repo: %s", opts.CloneOptions.URL()) // clone GitOps repo r, repofs, err := clone(ctx, opts.CloneOptions) diff --git a/pkg/application/application.go b/pkg/application/application.go index c73f1317..55de787c 100644 --- a/pkg/application/application.go +++ b/pkg/application/application.go @@ -454,20 +454,24 @@ func checkBaseCollision(repofs fs.FS, orgBasePath string, newBase *kusttypes.Kus } // fixResourcesPaths adjusts all relative paths in the kustomization file to the specified -// `kustomizationPath`. -func fixResourcesPaths(k *kusttypes.Kustomization, kustomizationPath string) error { +// newKustDir. +func fixResourcesPaths(k *kusttypes.Kustomization, newKustDir string) error { for i, path := range k.Resources { - // if path is a local file + // if path is a remote resource ignore it if _, err := os.Stat(path); err != nil && os.IsNotExist(err) { continue } - ap, err := filepath.Abs(path) + absRes, err := filepath.Abs(path) if err != nil { return err } - k.Resources[i], err = filepath.Rel(kustomizationPath, ap) + k.Resources[i], err = filepath.Rel(newKustDir, absRes) + log.G().WithFields(log.Fields{ + "from": absRes, + "to": k.Resources[i], + }).Debug("adjusting kustomization paths to local filesystem") if err != nil { return err } @@ -477,14 +481,18 @@ func fixResourcesPaths(k *kusttypes.Kustomization, kustomizationPath string) err } var generateManifests = func(k *kusttypes.Kustomization) ([]byte, error) { - td, err := ioutil.TempDir("", "auto-pilot") + td, err := ioutil.TempDir(".", "auto-pilot") if err != nil { return nil, err } defer os.RemoveAll(td) - kustomizationPath := filepath.Join(td, "kustomization.yaml") - if err = fixResourcesPaths(k, kustomizationPath); err != nil { + absTd, err := filepath.Abs(td) + if err != nil { + return nil, err + } + + if err = fixResourcesPaths(k, absTd); err != nil { return nil, err } @@ -493,6 +501,7 @@ var generateManifests = func(k *kusttypes.Kustomization) ([]byte, error) { return nil, err } + kustomizationPath := filepath.Join(td, "kustomization.yaml") if err = ioutil.WriteFile(kustomizationPath, kyaml, 0400); err != nil { return nil, err } diff --git a/pkg/git/repository.go b/pkg/git/repository.go index 702a6c27..9fe35219 100644 --- a/pkg/git/repository.go +++ b/pkg/git/repository.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "io" "os" "strings" @@ -38,7 +39,8 @@ type ( // URL clone url Repo string Auth Auth - FS billy.Filesystem + FS fs.FS + Progress io.Writer url string revision string path string @@ -77,9 +79,9 @@ var ( } ) -func AddFlags(cmd *cobra.Command, fs billy.Filesystem, prefix string) *CloneOptions { +func AddFlags(cmd *cobra.Command, bfs billy.Filesystem, prefix string) *CloneOptions { co := &CloneOptions{ - FS: fs, + FS: fs.Create(bfs), } if prefix == "" { @@ -193,11 +195,15 @@ var clone = func(ctx context.Context, opts *CloneOptions) (*repo, error) { return nil, ErrNilOpts } + if opts.Progress == nil { + opts.Progress = os.Stderr + } + cloneOpts := &gg.CloneOptions{ URL: opts.url, Auth: getAuth(opts.Auth), Depth: 1, - Progress: os.Stderr, + Progress: opts.Progress, Tags: gg.NoTags, } diff --git a/pkg/git/repository_test.go b/pkg/git/repository_test.go index 92bf81f7..6e0d734d 100644 --- a/pkg/git/repository_test.go +++ b/pkg/git/repository_test.go @@ -432,7 +432,7 @@ func TestClone(t *testing.T) { if tt.opts != nil { tt.opts.Parse() - tt.opts.FS = memfs.New() + tt.opts.FS = fs.Create(memfs.New()) } gotRepo, gotFS, err := tt.opts.Clone(context.Background())