From 1c812098ed95bc492d06de50133348f007ecbf24 Mon Sep 17 00:00:00 2001 From: Sanskar Bhushan Date: Fri, 9 Jun 2023 08:16:02 +0530 Subject: [PATCH 01/13] adding functionality to port create in a specified directory Signed-off-by: Sanskar Bhushan --- cmd/porter/bundle.go | 18 ++- docs/content/references/cli/bundles_create.md | 4 +- docs/content/references/cli/create.md | 4 +- pkg/porter/create.go | 56 ++++++-- pkg/porter/create_test.go | 121 +++++++++++++++++- pkg/porter/lifecycle_test.go | 2 +- 6 files changed, 185 insertions(+), 20 deletions(-) diff --git a/cmd/porter/bundle.go b/cmd/porter/bundle.go index faa12275d..bd367adb6 100644 --- a/cmd/porter/bundle.go +++ b/cmd/porter/bundle.go @@ -31,14 +31,24 @@ func buildBundleCommands(p *porter.Porter) *cobra.Command { } func buildBundleCreateCommand(p *porter.Porter) *cobra.Command { - return &cobra.Command{ - Use: "create", + cmd := &cobra.Command{ + Use: "create [bundle-name]", Short: "Create a bundle", - Long: "Create a bundle. This generates a porter bundle in the current directory.", + Long: "Create a bundle. This generates a porter bundle in the directory with the specified name or in the current directory if no name is provided.", + Args: cobra.MaximumNArgs(1), // Expect at most one argument for the bundle name RunE: func(cmd *cobra.Command, args []string) error { - return p.Create() + // By default we create the bundle in the current directory + bundleName := "" + + if len(args) > 0 { + bundleName = args[0] + } + + return p.Create(bundleName) }, } + + return cmd } func buildBundleBuildCommand(p *porter.Porter) *cobra.Command { diff --git a/docs/content/references/cli/bundles_create.md b/docs/content/references/cli/bundles_create.md index 706d0ef77..3abfb8200 100644 --- a/docs/content/references/cli/bundles_create.md +++ b/docs/content/references/cli/bundles_create.md @@ -9,10 +9,10 @@ Create a bundle ### Synopsis -Create a bundle. This generates a porter bundle in the current directory. +Create a bundle. This generates a porter bundle in the directory with the specified name or in the current directory if no name is provided. ``` -porter bundles create [flags] +porter bundles create [bundle-name] [flags] ``` ### Options diff --git a/docs/content/references/cli/create.md b/docs/content/references/cli/create.md index f505582d7..2ac4414cd 100644 --- a/docs/content/references/cli/create.md +++ b/docs/content/references/cli/create.md @@ -9,10 +9,10 @@ Create a bundle ### Synopsis -Create a bundle. This generates a porter bundle in the current directory. +Create a bundle. This generates a porter bundle in the directory with the specified name or in the current directory if no name is provided. ``` -porter create [flags] +porter create [bundle-name] [flags] ``` ### Options diff --git a/pkg/porter/create.go b/pkg/porter/create.go index ef0a88d0f..924948d84 100644 --- a/pkg/porter/create.go +++ b/pkg/porter/create.go @@ -4,40 +4,80 @@ import ( "fmt" "os" "path/filepath" + "strings" "get.porter.sh/porter/pkg" "get.porter.sh/porter/pkg/config" ) -func (p *Porter) Create() error { - fmt.Fprintln(p.Out, "creating porter configuration in the current directory") +// Create function creates a porter configuration in the specified directory or in the current directory if no directory is specified. +func (p *Porter) Create(bundleName string) error { + // Normalize the bundleName by removing trailing slashes + bundleName = strings.TrimSuffix(bundleName, "/") - err := p.CopyTemplate(p.Templates.GetManifest, config.Name) + // Use the current directory if no directory is passed + if bundleName == "" { + bundleName = p.FileSystem.Getwd() + } + + // Check if the directory in which bundle needs to be created already exists. + // If not, create the directory. + _, err := os.Stat(bundleName) + if err != nil { + if os.IsNotExist(err) { + // This code here attempts to create the directory in which bundle needs to be created, + // if the directory does not exist. + // bundleName can handle both the relative path and absolute path into consideration, + // For example if we want to create a bundle named mybundle in an existing directory /home/user we can call porter create /home/user/mybundle or porter create mybundle in the /home/user directory. + // If we are in a directory /home/user and we want to create mybundle in the directory /home/user/directory given the directory exists, + // we can call porter create directory/mybundle from the /home/user directory or with any relative paths' combinations that one can come up with. + // Only condition to use porter create with absolute and relative paths is that all the directories in the path except the last one should strictly exist. + err = os.Mkdir(bundleName, os.ModePerm) + // This error message is returned when the os.Mkdir call encounters an error + // during the directory creation process. It specifically indicates that the attempt + // to create the bundle directory failed. This could occur due to reasons such as + // lack of permissions, a file system error, or if the parent directory doesn't exist. + if err != nil { + return fmt.Errorf("failed to create directory for bundle: %w", err) + } + // This error message is returned when the os.Stat call encounters an error other than + // the directory not existing. It implies that there was an issue with checking the bundle directory, + // but it doesn't mean that the directory creation itself failed. + // It could be due to various reasons, such as insufficient permissions, an invalid directory path, + // or other file system-related errors. + } else { + return fmt.Errorf("failed to check bundle directory: %w", err) + } + } + + err = p.CopyTemplate(p.Templates.GetManifest, filepath.Join(bundleName, config.Name)) if err != nil { return err } - err = p.CopyTemplate(p.Templates.GetManifestHelpers, "helpers.sh") + err = p.CopyTemplate(p.Templates.GetManifestHelpers, filepath.Join(bundleName, "helpers.sh")) if err != nil { return err } - err = p.CopyTemplate(p.Templates.GetReadme, "README.md") + err = p.CopyTemplate(p.Templates.GetReadme, filepath.Join(bundleName, "README.md")) if err != nil { return err } - err = p.CopyTemplate(p.Templates.GetDockerfileTemplate, "template.Dockerfile") + err = p.CopyTemplate(p.Templates.GetDockerfileTemplate, filepath.Join(bundleName, "template.Dockerfile")) if err != nil { return err } - err = p.CopyTemplate(p.Templates.GetDockerignore, ".dockerignore") + err = p.CopyTemplate(p.Templates.GetDockerignore, filepath.Join(bundleName, ".dockerignore")) if err != nil { return err } - return p.CopyTemplate(p.Templates.GetGitignore, ".gitignore") + fmt.Fprintf(p.Out, "creating porter configuration in %s\n", bundleName) + + return p.CopyTemplate(p.Templates.GetGitignore, filepath.Join(bundleName, ".gitignore")) } func (p *Porter) CopyTemplate(getTemplate func() ([]byte, error), dest string) error { diff --git a/pkg/porter/create_test.go b/pkg/porter/create_test.go index 5773c2a52..192e697da 100644 --- a/pkg/porter/create_test.go +++ b/pkg/porter/create_test.go @@ -1,6 +1,8 @@ package porter import ( + "os" + "path/filepath" "testing" "get.porter.sh/porter/pkg" @@ -8,18 +10,18 @@ import ( "github.com/stretchr/testify/require" ) -func TestCreate(t *testing.T) { +func TestCreateInRootDirectory(t *testing.T) { p := NewTestPorter(t) defer p.Close() - err := p.Create() + err := p.Create("") require.NoError(t, err) + // Verify that files are present in the root directory configFileStats, err := p.FileSystem.Stat("porter.yaml") require.NoError(t, err) tests.AssertFilePermissionsEqual(t, "porter.yaml", pkg.FileModeWritable, configFileStats.Mode()) - // Verify that helpers is present and executable helperFileStats, err := p.FileSystem.Stat("helpers.sh") require.NoError(t, err) tests.AssertFilePermissionsEqual(t, "helpers.sh", pkg.FileModeExecutable, helperFileStats.Mode()) @@ -39,5 +41,118 @@ func TestCreate(t *testing.T) { dockerignoreStats, err := p.FileSystem.Stat(".dockerignore") require.NoError(t, err) tests.AssertFilePermissionsEqual(t, ".dockerignore", pkg.FileModeWritable, dockerignoreStats.Mode()) +} + +// tests to ensure behavior similarity with helm create + +func TestCreateInDirectory(t *testing.T) { + // Create a temporary directory for testing + tempDir := os.TempDir() + bundleDir := filepath.Join(tempDir, "mybundle") + + p := NewTestPorter(t) + err := p.Create(bundleDir) + require.NoError(t, err) + + // Verify that files are present in the "mybundle" directory + configFileStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, "porter.yaml")) + require.NoError(t, err) + tests.AssertFilePermissionsEqual(t, filepath.Join("mybundle", "porter.yaml"), pkg.FileModeWritable, configFileStats.Mode()) + + helperFileStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, "helpers.sh")) + require.NoError(t, err) + tests.AssertFilePermissionsEqual(t, filepath.Join("mybundle", "helpers.sh"), pkg.FileModeExecutable, helperFileStats.Mode()) + + dockerfileStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, "template.Dockerfile")) + require.NoError(t, err) + tests.AssertFilePermissionsEqual(t, filepath.Join("mybundle", "template.Dockerfile"), pkg.FileModeWritable, dockerfileStats.Mode()) + + readmeStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, "README.md")) + require.NoError(t, err) + tests.AssertFilePermissionsEqual(t, filepath.Join("mybundle", "README.md"), pkg.FileModeWritable, readmeStats.Mode()) + + gitignoreStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, ".gitignore")) + require.NoError(t, err) + tests.AssertFilePermissionsEqual(t, filepath.Join("mybundle", ".gitignore"), pkg.FileModeWritable, gitignoreStats.Mode()) + + dockerignoreStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, ".dockerignore")) + require.NoError(t, err) + tests.AssertFilePermissionsEqual(t, filepath.Join("mybundle", ".dockerignore"), pkg.FileModeWritable, dockerignoreStats.Mode()) +} + +func TestCreateInChildDirectoryWithoutExistingParentDirectory(t *testing.T) { + // Create a temporary directory for testing + tempDir := os.TempDir() + parentDir := filepath.Join(tempDir, "parentbundle") + err := os.Mkdir(parentDir, os.ModePerm) + require.NoError(t, err) + + // Define the child directory within the existing parent directory + bundleDir := filepath.Join(parentDir, "childbundle") + + p := NewTestPorter(t) + err = p.Create(bundleDir) + + // Verify that the expected error is returned + require.Error(t, err) + require.Contains(t, err.Error(), "failed to create directory for bundle") + // Verify that no files are created in the subdirectory + _, err = p.FileSystem.Stat(filepath.Join(bundleDir, "porter.yaml")) + require.True(t, os.IsNotExist(err)) + + _, err = p.FileSystem.Stat(filepath.Join(bundleDir, "helpers.sh")) + require.True(t, os.IsNotExist(err)) + + _, err = p.FileSystem.Stat(filepath.Join(bundleDir, "template.Dockerfile")) + require.True(t, os.IsNotExist(err)) + + _, err = p.FileSystem.Stat(filepath.Join(bundleDir, "README.md")) + require.True(t, os.IsNotExist(err)) + + _, err = p.FileSystem.Stat(filepath.Join(bundleDir, ".gitignore")) + require.True(t, os.IsNotExist(err)) + + _, err = p.FileSystem.Stat(filepath.Join(bundleDir, ".dockerignore")) + require.True(t, os.IsNotExist(err)) +} + +func TestCreateInChildDirectoryWithExistingParentDirectory(t *testing.T) { + // Create a temporary directory for testing + tempDir := os.TempDir() + parentDir := filepath.Join(tempDir, "parentbundle") + err := os.Mkdir(parentDir, os.ModePerm) + require.NoError(t, err) + + // Define the child directory within the existing parent directory + bundleDir := filepath.Join(parentDir, "childbundle") + + p := NewTestPorter(t) + err = p.Create(bundleDir) + require.NoError(t, err) + + // Verify that files are present in the child directory + configFileStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, "porter.yaml")) + require.NoError(t, err) + tests.AssertFilePermissionsEqual(t, filepath.Join("parentbundle/childbundle", "porter.yaml"), pkg.FileModeWritable, configFileStats.Mode()) + + helperFileStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, "helpers.sh")) + require.NoError(t, err) + tests.AssertFilePermissionsEqual(t, filepath.Join("parentbundle/childbundle", "helpers.sh"), pkg.FileModeExecutable, helperFileStats.Mode()) + + dockerfileStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, "template.Dockerfile")) + require.NoError(t, err) + tests.AssertFilePermissionsEqual(t, filepath.Join("parentbundle/childbundle", "template.Dockerfile"), pkg.FileModeWritable, dockerfileStats.Mode()) + + readmeStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, "README.md")) + require.NoError(t, err) + tests.AssertFilePermissionsEqual(t, filepath.Join("parentbundle/childbundle", "README.md"), pkg.FileModeWritable, readmeStats.Mode()) + + gitignoreStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, ".gitignore")) + require.NoError(t, err) + tests.AssertFilePermissionsEqual(t, filepath.Join("parentbundle/childbundle", ".gitignore"), pkg.FileModeWritable, gitignoreStats.Mode()) + + dockerignoreStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, ".dockerignore")) + require.NoError(t, err) + tests.AssertFilePermissionsEqual(t, filepath.Join("parentbundle/childbundle", ".dockerignore"), pkg.FileModeWritable, dockerignoreStats.Mode()) } diff --git a/pkg/porter/lifecycle_test.go b/pkg/porter/lifecycle_test.go index 8d7926611..5859993fa 100644 --- a/pkg/porter/lifecycle_test.go +++ b/pkg/porter/lifecycle_test.go @@ -28,7 +28,7 @@ func TestInstallFromTagIgnoresCurrentBundle(t *testing.T) { p := NewTestPorter(t) defer p.Close() - err := p.Create() + err := p.Create("") require.NoError(t, err) installOpts := NewInstallOptions() From ecea4efdb155662794a6a05dc90ee276a6575d89 Mon Sep 17 00:00:00 2001 From: Ludvig Liljenberg Date: Fri, 1 Sep 2023 11:36:50 -0700 Subject: [PATCH 02/13] add warning when overwriting file + fix comments Signed-off-by: Ludvig Liljenberg --- pkg/porter/create.go | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/pkg/porter/create.go b/pkg/porter/create.go index 924948d84..783692114 100644 --- a/pkg/porter/create.go +++ b/pkg/porter/create.go @@ -1,6 +1,7 @@ package porter import ( + "errors" "fmt" "os" "path/filepath" @@ -23,30 +24,10 @@ func (p *Porter) Create(bundleName string) error { // Check if the directory in which bundle needs to be created already exists. // If not, create the directory. _, err := os.Stat(bundleName) - if err != nil { - if os.IsNotExist(err) { - // This code here attempts to create the directory in which bundle needs to be created, - // if the directory does not exist. - // bundleName can handle both the relative path and absolute path into consideration, - // For example if we want to create a bundle named mybundle in an existing directory /home/user we can call porter create /home/user/mybundle or porter create mybundle in the /home/user directory. - // If we are in a directory /home/user and we want to create mybundle in the directory /home/user/directory given the directory exists, - // we can call porter create directory/mybundle from the /home/user directory or with any relative paths' combinations that one can come up with. - // Only condition to use porter create with absolute and relative paths is that all the directories in the path except the last one should strictly exist. - err = os.Mkdir(bundleName, os.ModePerm) - // This error message is returned when the os.Mkdir call encounters an error - // during the directory creation process. It specifically indicates that the attempt - // to create the bundle directory failed. This could occur due to reasons such as - // lack of permissions, a file system error, or if the parent directory doesn't exist. - if err != nil { - return fmt.Errorf("failed to create directory for bundle: %w", err) - } - // This error message is returned when the os.Stat call encounters an error other than - // the directory not existing. It implies that there was an issue with checking the bundle directory, - // but it doesn't mean that the directory creation itself failed. - // It could be due to various reasons, such as insufficient permissions, an invalid directory path, - // or other file system-related errors. - } else { - return fmt.Errorf("failed to check bundle directory: %w", err) + if err != nil && errors.Is(err, os.ErrNotExist) { + err = os.Mkdir(bundleName, os.ModePerm) + if err != nil { + return fmt.Errorf("failed to create directory for bundle: %w", err) } } @@ -75,8 +56,6 @@ func (p *Porter) Create(bundleName string) error { return err } - fmt.Fprintf(p.Out, "creating porter configuration in %s\n", bundleName) - return p.CopyTemplate(p.Templates.GetGitignore, filepath.Join(bundleName, ".gitignore")) } @@ -90,7 +69,9 @@ func (p *Porter) CopyTemplate(getTemplate func() ([]byte, error), dest string) e if filepath.Ext(dest) == ".sh" { mode = pkg.FileModeExecutable } - + if _, err := os.Stat(dest); err == nil { + fmt.Fprintf(os.Stderr, "WARNING: File %q already exists. Overwriting.\n", dest) + } err = p.FileSystem.WriteFile(dest, tmpl, mode) if err != nil { return fmt.Errorf("failed to write template to %s: %w", dest, err) From 851b9234dfa4c03594d609b410d8832e62808d1b Mon Sep 17 00:00:00 2001 From: Ludvig Liljenberg Date: Fri, 1 Sep 2023 15:44:07 -0700 Subject: [PATCH 03/13] fixes Signed-off-by: Ludvig Liljenberg --- pkg/porter/create.go | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/pkg/porter/create.go b/pkg/porter/create.go index 783692114..ab41d0847 100644 --- a/pkg/porter/create.go +++ b/pkg/porter/create.go @@ -12,26 +12,34 @@ import ( ) // Create function creates a porter configuration in the specified directory or in the current directory if no directory is specified. +// The bundle's name will be `bundleName`, or "porter_hello" if bundleName is the empty string func (p *Porter) Create(bundleName string) error { // Normalize the bundleName by removing trailing slashes bundleName = strings.TrimSuffix(bundleName, "/") - // Use the current directory if no directory is passed - if bundleName == "" { - bundleName = p.FileSystem.Getwd() - } - - // Check if the directory in which bundle needs to be created already exists. - // If not, create the directory. + // Create given directory if it doesn't exist _, err := os.Stat(bundleName) if err != nil && errors.Is(err, os.ErrNotExist) { - err = os.Mkdir(bundleName, os.ModePerm) + err = os.MkdirAll(bundleName, os.ModePerm) // if given bundleName is foo/bar, will create both foo and bar directories if err != nil { return fmt.Errorf("failed to create directory for bundle: %w", err) } } - err = p.CopyTemplate(p.Templates.GetManifest, filepath.Join(bundleName, config.Name)) + if bundleName == "" { + // create bundle with default name "porter_hello" + err = p.CopyTemplate(p.Templates.GetManifest, filepath.Join(bundleName, config.Name)) + } else { + // create bundle with given name + err = p.CopyTemplate(func() ([]byte, error) { + content, err := p.Templates.GetManifest() + if err != nil { + return nil, err + } + strings.ReplaceAll(string(content), "porter_hello", bundleName) + return content, nil + }, filepath.Join(bundleName, config.Name)) + } if err != nil { return err } From 3771be2a2033c04b743fafb32aab2e6c9e67eb1a Mon Sep 17 00:00:00 2001 From: Ludvig Liljenberg Date: Fri, 1 Sep 2023 16:04:49 -0700 Subject: [PATCH 04/13] fix Signed-off-by: Ludvig Liljenberg --- pkg/porter/create.go | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/pkg/porter/create.go b/pkg/porter/create.go index ab41d0847..e3b2bcaf9 100644 --- a/pkg/porter/create.go +++ b/pkg/porter/create.go @@ -12,20 +12,23 @@ import ( ) // Create function creates a porter configuration in the specified directory or in the current directory if no directory is specified. -// The bundle's name will be `bundleName`, or "porter_hello" if bundleName is the empty string +// The bundle's name will be the given bundleName, or "porter_hello" if bundleName is the empty string func (p *Porter) Create(bundleName string) error { // Normalize the bundleName by removing trailing slashes bundleName = strings.TrimSuffix(bundleName, "/") - // Create given directory if it doesn't exist - _, err := os.Stat(bundleName) - if err != nil && errors.Is(err, os.ErrNotExist) { - err = os.MkdirAll(bundleName, os.ModePerm) // if given bundleName is foo/bar, will create both foo and bar directories - if err != nil { - return fmt.Errorf("failed to create directory for bundle: %w", err) + // If given a bundleName, create directory if it doesn't exist + if bundleName != "" { + _, err := os.Stat(bundleName) + if err != nil && errors.Is(err, os.ErrNotExist) { + err = os.Mkdir(bundleName, os.ModePerm) + if err != nil { + return fmt.Errorf("failed to create directory for bundle: %w", err) + } } } + var err error if bundleName == "" { // create bundle with default name "porter_hello" err = p.CopyTemplate(p.Templates.GetManifest, filepath.Join(bundleName, config.Name)) @@ -36,7 +39,7 @@ func (p *Porter) Create(bundleName string) error { if err != nil { return nil, err } - strings.ReplaceAll(string(content), "porter_hello", bundleName) + content = []byte(strings.ReplaceAll(string(content), "porter-hello", bundleName)) return content, nil }, filepath.Join(bundleName, config.Name)) } From 4f1052240efd930970bb6aeee31077bdf57f6d01 Mon Sep 17 00:00:00 2001 From: Ludvig Liljenberg Date: Fri, 1 Sep 2023 16:05:31 -0700 Subject: [PATCH 05/13] forgot this file Signed-off-by: Ludvig Liljenberg --- cmd/porter/bundle.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cmd/porter/bundle.go b/cmd/porter/bundle.go index bd367adb6..fc9a2bd2a 100644 --- a/cmd/porter/bundle.go +++ b/cmd/porter/bundle.go @@ -31,15 +31,14 @@ func buildBundleCommands(p *porter.Porter) *cobra.Command { } func buildBundleCreateCommand(p *porter.Porter) *cobra.Command { - cmd := &cobra.Command{ + return &cobra.Command{ Use: "create [bundle-name]", Short: "Create a bundle", - Long: "Create a bundle. This generates a porter bundle in the directory with the specified name or in the current directory if no name is provided.", + Long: "Create a bundle. This command creates a new porter bundle with the specified bundle-name, in the directory with the specified bundle-name. If no bundle-name is provided, the bundle will be created in current directory and the bundle name will be 'porter-hello'.", Args: cobra.MaximumNArgs(1), // Expect at most one argument for the bundle name RunE: func(cmd *cobra.Command, args []string) error { // By default we create the bundle in the current directory bundleName := "" - if len(args) > 0 { bundleName = args[0] } @@ -47,8 +46,6 @@ func buildBundleCreateCommand(p *porter.Porter) *cobra.Command { return p.Create(bundleName) }, } - - return cmd } func buildBundleBuildCommand(p *porter.Porter) *cobra.Command { From f7f23952a7138881d96224d17cf628bb424f5a09 Mon Sep 17 00:00:00 2001 From: Ludvig Liljenberg Date: Fri, 1 Sep 2023 16:07:37 -0700 Subject: [PATCH 06/13] fix Signed-off-by: Ludvig Liljenberg --- pkg/porter/create.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/porter/create.go b/pkg/porter/create.go index e3b2bcaf9..2df2b560e 100644 --- a/pkg/porter/create.go +++ b/pkg/porter/create.go @@ -11,7 +11,7 @@ import ( "get.porter.sh/porter/pkg/config" ) -// Create function creates a porter configuration in the specified directory or in the current directory if no directory is specified. +// Create function creates a porter configuration in the specified directory (bundleName) or in the current directory if no directory is specified. // The bundle's name will be the given bundleName, or "porter_hello" if bundleName is the empty string func (p *Porter) Create(bundleName string) error { // Normalize the bundleName by removing trailing slashes From 60a9ce0f9f6ffcd77bc0a53e516ede2922f0f7f4 Mon Sep 17 00:00:00 2001 From: Ludvig Liljenberg Date: Tue, 5 Sep 2023 11:04:18 -0700 Subject: [PATCH 07/13] fixed tests Signed-off-by: Ludvig Liljenberg --- pkg/porter/build_integration_test.go | 4 +- pkg/porter/create.go | 5 +- pkg/porter/create_test.go | 121 ++++++--------------------- tests/integration/invoke_test.go | 2 +- tests/integration/outputs_test.go | 2 +- 5 files changed, 32 insertions(+), 102 deletions(-) diff --git a/pkg/porter/build_integration_test.go b/pkg/porter/build_integration_test.go index 1998f86f9..fcf942fe8 100644 --- a/pkg/porter/build_integration_test.go +++ b/pkg/porter/build_integration_test.go @@ -144,7 +144,7 @@ func TestPorter_LintDuringBuild(t *testing.T) { testMixins := p.Mixins.(*mixin.TestMixinProvider) testMixins.LintResults = lintResults - err := p.Create() + err := p.Create("mybundle") require.NoError(t, err, "Create failed") opts := BuildOptions{NoLint: false} @@ -163,7 +163,7 @@ func TestPorter_LintDuringBuild(t *testing.T) { testMixins := p.Mixins.(*mixin.TestMixinProvider) testMixins.LintResults = lintResults - err := p.Create() + err := p.Create("mybundle") require.NoError(t, err, "Create failed") opts := BuildOptions{NoLint: true} diff --git a/pkg/porter/create.go b/pkg/porter/create.go index 2df2b560e..95b426523 100644 --- a/pkg/porter/create.go +++ b/pkg/porter/create.go @@ -11,8 +11,8 @@ import ( "get.porter.sh/porter/pkg/config" ) -// Create function creates a porter configuration in the specified directory (bundleName) or in the current directory if no directory is specified. -// The bundle's name will be the given bundleName, or "porter_hello" if bundleName is the empty string +// Create creates a new bundle configuration with the specified bundleName. A directory with the given bundleName will be created if it does not already exist. +// If bundleName is the empty string, the configuration will be created in the current directory, and the name will be "porter-hello". func (p *Porter) Create(bundleName string) error { // Normalize the bundleName by removing trailing slashes bundleName = strings.TrimSuffix(bundleName, "/") @@ -80,6 +80,7 @@ func (p *Porter) CopyTemplate(getTemplate func() ([]byte, error), dest string) e if filepath.Ext(dest) == ".sh" { mode = pkg.FileModeExecutable } + if _, err := os.Stat(dest); err == nil { fmt.Fprintf(os.Stderr, "WARNING: File %q already exists. Overwriting.\n", dest) } diff --git a/pkg/porter/create_test.go b/pkg/porter/create_test.go index 192e697da..61589c247 100644 --- a/pkg/porter/create_test.go +++ b/pkg/porter/create_test.go @@ -1,7 +1,9 @@ package porter import ( - "os" + "get.porter.sh/porter/pkg/manifest" + "get.porter.sh/porter/pkg/yaml" + "github.com/stretchr/testify/assert" "path/filepath" "testing" @@ -10,7 +12,7 @@ import ( "github.com/stretchr/testify/require" ) -func TestCreateInRootDirectory(t *testing.T) { +func TestCreateInWorkingDirectory(t *testing.T) { p := NewTestPorter(t) defer p.Close() @@ -44,115 +46,42 @@ func TestCreateInRootDirectory(t *testing.T) { } // tests to ensure behavior similarity with helm create - -func TestCreateInDirectory(t *testing.T) { - // Create a temporary directory for testing - tempDir := os.TempDir() - bundleDir := filepath.Join(tempDir, "mybundle") +func TestCreateWithBundleName(t *testing.T) { + bundleName := "mybundle" p := NewTestPorter(t) - err := p.Create(bundleDir) + err := p.Create(bundleName) require.NoError(t, err) // Verify that files are present in the "mybundle" directory - configFileStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, "porter.yaml")) - require.NoError(t, err) - tests.AssertFilePermissionsEqual(t, filepath.Join("mybundle", "porter.yaml"), pkg.FileModeWritable, configFileStats.Mode()) - - helperFileStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, "helpers.sh")) - require.NoError(t, err) - tests.AssertFilePermissionsEqual(t, filepath.Join("mybundle", "helpers.sh"), pkg.FileModeExecutable, helperFileStats.Mode()) - - dockerfileStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, "template.Dockerfile")) - require.NoError(t, err) - tests.AssertFilePermissionsEqual(t, filepath.Join("mybundle", "template.Dockerfile"), pkg.FileModeWritable, dockerfileStats.Mode()) - - readmeStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, "README.md")) - require.NoError(t, err) - tests.AssertFilePermissionsEqual(t, filepath.Join("mybundle", "README.md"), pkg.FileModeWritable, readmeStats.Mode()) - - gitignoreStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, ".gitignore")) - require.NoError(t, err) - tests.AssertFilePermissionsEqual(t, filepath.Join("mybundle", ".gitignore"), pkg.FileModeWritable, gitignoreStats.Mode()) - - dockerignoreStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, ".dockerignore")) - require.NoError(t, err) - tests.AssertFilePermissionsEqual(t, filepath.Join("mybundle", ".dockerignore"), pkg.FileModeWritable, dockerignoreStats.Mode()) -} - -func TestCreateInChildDirectoryWithoutExistingParentDirectory(t *testing.T) { - // Create a temporary directory for testing - tempDir := os.TempDir() - parentDir := filepath.Join(tempDir, "parentbundle") - err := os.Mkdir(parentDir, os.ModePerm) - require.NoError(t, err) - - // Define the child directory within the existing parent directory - bundleDir := filepath.Join(parentDir, "childbundle") - - p := NewTestPorter(t) - err = p.Create(bundleDir) - - // Verify that the expected error is returned - require.Error(t, err) - require.Contains(t, err.Error(), "failed to create directory for bundle") - - // Verify that no files are created in the subdirectory - _, err = p.FileSystem.Stat(filepath.Join(bundleDir, "porter.yaml")) - require.True(t, os.IsNotExist(err)) - - _, err = p.FileSystem.Stat(filepath.Join(bundleDir, "helpers.sh")) - require.True(t, os.IsNotExist(err)) - - _, err = p.FileSystem.Stat(filepath.Join(bundleDir, "template.Dockerfile")) - require.True(t, os.IsNotExist(err)) - - _, err = p.FileSystem.Stat(filepath.Join(bundleDir, "README.md")) - require.True(t, os.IsNotExist(err)) - - _, err = p.FileSystem.Stat(filepath.Join(bundleDir, ".gitignore")) - require.True(t, os.IsNotExist(err)) - - _, err = p.FileSystem.Stat(filepath.Join(bundleDir, ".dockerignore")) - require.True(t, os.IsNotExist(err)) -} - -func TestCreateInChildDirectoryWithExistingParentDirectory(t *testing.T) { - // Create a temporary directory for testing - tempDir := os.TempDir() - parentDir := filepath.Join(tempDir, "parentbundle") - err := os.Mkdir(parentDir, os.ModePerm) - require.NoError(t, err) - - // Define the child directory within the existing parent directory - bundleDir := filepath.Join(parentDir, "childbundle") - - p := NewTestPorter(t) - err = p.Create(bundleDir) + configFileStats, err := p.FileSystem.Stat(filepath.Join(bundleName, "porter.yaml")) require.NoError(t, err) + tests.AssertFilePermissionsEqual(t, filepath.Join(bundleName, "porter.yaml"), pkg.FileModeWritable, configFileStats.Mode()) - // Verify that files are present in the child directory - configFileStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, "porter.yaml")) + helperFileStats, err := p.FileSystem.Stat(filepath.Join(bundleName, "helpers.sh")) require.NoError(t, err) - tests.AssertFilePermissionsEqual(t, filepath.Join("parentbundle/childbundle", "porter.yaml"), pkg.FileModeWritable, configFileStats.Mode()) + tests.AssertFilePermissionsEqual(t, filepath.Join(bundleName, "helpers.sh"), pkg.FileModeExecutable, helperFileStats.Mode()) - helperFileStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, "helpers.sh")) + dockerfileStats, err := p.FileSystem.Stat(filepath.Join(bundleName, "template.Dockerfile")) require.NoError(t, err) - tests.AssertFilePermissionsEqual(t, filepath.Join("parentbundle/childbundle", "helpers.sh"), pkg.FileModeExecutable, helperFileStats.Mode()) + tests.AssertFilePermissionsEqual(t, filepath.Join(bundleName, "template.Dockerfile"), pkg.FileModeWritable, dockerfileStats.Mode()) - dockerfileStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, "template.Dockerfile")) + readmeStats, err := p.FileSystem.Stat(filepath.Join(bundleName, "README.md")) require.NoError(t, err) - tests.AssertFilePermissionsEqual(t, filepath.Join("parentbundle/childbundle", "template.Dockerfile"), pkg.FileModeWritable, dockerfileStats.Mode()) + tests.AssertFilePermissionsEqual(t, filepath.Join(bundleName, "README.md"), pkg.FileModeWritable, readmeStats.Mode()) - readmeStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, "README.md")) + gitignoreStats, err := p.FileSystem.Stat(filepath.Join(bundleName, ".gitignore")) require.NoError(t, err) - tests.AssertFilePermissionsEqual(t, filepath.Join("parentbundle/childbundle", "README.md"), pkg.FileModeWritable, readmeStats.Mode()) + tests.AssertFilePermissionsEqual(t, filepath.Join(bundleName, ".gitignore"), pkg.FileModeWritable, gitignoreStats.Mode()) - gitignoreStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, ".gitignore")) + dockerignoreStats, err := p.FileSystem.Stat(filepath.Join(bundleName, ".dockerignore")) require.NoError(t, err) - tests.AssertFilePermissionsEqual(t, filepath.Join("parentbundle/childbundle", ".gitignore"), pkg.FileModeWritable, gitignoreStats.Mode()) + tests.AssertFilePermissionsEqual(t, filepath.Join(bundleName, ".dockerignore"), pkg.FileModeWritable, dockerignoreStats.Mode()) - dockerignoreStats, err := p.FileSystem.Stat(filepath.Join(bundleDir, ".dockerignore")) - require.NoError(t, err) - tests.AssertFilePermissionsEqual(t, filepath.Join("parentbundle/childbundle", ".dockerignore"), pkg.FileModeWritable, dockerignoreStats.Mode()) + // verify "name" inside porter.yaml is set to "mybundle" + porterYaml := &manifest.Manifest{} + data, err := p.FileSystem.ReadFile(filepath.Join(bundleName, "porter.yaml")) + assert.NoError(t, err) + assert.NoError(t, yaml.Unmarshal(data, &porterYaml)) + assert.True(t, porterYaml.Name == bundleName) } diff --git a/tests/integration/invoke_test.go b/tests/integration/invoke_test.go index e14907597..16ff2f67f 100644 --- a/tests/integration/invoke_test.go +++ b/tests/integration/invoke_test.go @@ -22,7 +22,7 @@ func TestInvokeCustomAction(t *testing.T) { ctx := p.SetupIntegrationTest() // Install a bundle with a custom action defined - err := p.Create() + err := p.Create("") require.NoError(t, err) bundleName := p.AddTestBundleDir("testdata/bundles/bundle-with-custom-action", true) diff --git a/tests/integration/outputs_test.go b/tests/integration/outputs_test.go index 6529b6956..4ee576cb8 100644 --- a/tests/integration/outputs_test.go +++ b/tests/integration/outputs_test.go @@ -79,7 +79,7 @@ func CleanupCurrentBundle(ctx context.Context, p *porter.TestPorter) { } func installExecOutputsBundle(ctx context.Context, p *porter.TestPorter) string { - err := p.Create() + err := p.Create("") require.NoError(p.T(), err) bundleName := p.AddTestBundleDir("testdata/bundles/exec-outputs", true) From 7fa75dad33e93439bbd4abe7e01a428c4e4f1c4c Mon Sep 17 00:00:00 2001 From: Ludvig Liljenberg Date: Tue, 5 Sep 2023 14:35:54 -0700 Subject: [PATCH 08/13] feedback Signed-off-by: Ludvig Liljenberg --- cmd/porter/bundle.go | 13 +++-- pkg/porter/build_integration_test.go | 4 +- pkg/porter/create.go | 76 +++++++++++++++------------- pkg/porter/create_test.go | 15 +++--- pkg/porter/lifecycle_test.go | 2 +- tests/integration/invoke_test.go | 2 +- tests/integration/outputs_test.go | 2 +- 7 files changed, 60 insertions(+), 54 deletions(-) diff --git a/cmd/porter/bundle.go b/cmd/porter/bundle.go index fc9a2bd2a..237e81b78 100644 --- a/cmd/porter/bundle.go +++ b/cmd/porter/bundle.go @@ -34,16 +34,15 @@ func buildBundleCreateCommand(p *porter.Porter) *cobra.Command { return &cobra.Command{ Use: "create [bundle-name]", Short: "Create a bundle", - Long: "Create a bundle. This command creates a new porter bundle with the specified bundle-name, in the directory with the specified bundle-name. If no bundle-name is provided, the bundle will be created in current directory and the bundle name will be 'porter-hello'.", - Args: cobra.MaximumNArgs(1), // Expect at most one argument for the bundle name + Long: "Create a bundle. This command creates a new porter bundle with the specified bundle-name, in the directory with the specified bundle-name." + + " The directory will be created if it doesn't already exist. If no bundle-name is provided, the bundle will be created in current directory and the bundle name will be 'porter-hello'.", + Args: cobra.MaximumNArgs(1), // Expect at most one argument for the bundle name RunE: func(cmd *cobra.Command, args []string) error { - // By default we create the bundle in the current directory - bundleName := "" if len(args) > 0 { - bundleName = args[0] + bundleName := args[0] + return p.CreateInDir(bundleName) } - - return p.Create(bundleName) + return p.Create() }, } } diff --git a/pkg/porter/build_integration_test.go b/pkg/porter/build_integration_test.go index fcf942fe8..1998f86f9 100644 --- a/pkg/porter/build_integration_test.go +++ b/pkg/porter/build_integration_test.go @@ -144,7 +144,7 @@ func TestPorter_LintDuringBuild(t *testing.T) { testMixins := p.Mixins.(*mixin.TestMixinProvider) testMixins.LintResults = lintResults - err := p.Create("mybundle") + err := p.Create() require.NoError(t, err, "Create failed") opts := BuildOptions{NoLint: false} @@ -163,7 +163,7 @@ func TestPorter_LintDuringBuild(t *testing.T) { testMixins := p.Mixins.(*mixin.TestMixinProvider) testMixins.LintResults = lintResults - err := p.Create("mybundle") + err := p.Create() require.NoError(t, err, "Create failed") opts := BuildOptions{NoLint: true} diff --git a/pkg/porter/create.go b/pkg/porter/create.go index 95b426523..8e36068e6 100644 --- a/pkg/porter/create.go +++ b/pkg/porter/create.go @@ -11,63 +11,71 @@ import ( "get.porter.sh/porter/pkg/config" ) -// Create creates a new bundle configuration with the specified bundleName. A directory with the given bundleName will be created if it does not already exist. -// If bundleName is the empty string, the configuration will be created in the current directory, and the name will be "porter-hello". -func (p *Porter) Create(bundleName string) error { - // Normalize the bundleName by removing trailing slashes - bundleName = strings.TrimSuffix(bundleName, "/") - - // If given a bundleName, create directory if it doesn't exist - if bundleName != "" { - _, err := os.Stat(bundleName) - if err != nil && errors.Is(err, os.ErrNotExist) { - err = os.Mkdir(bundleName, os.ModePerm) - if err != nil { - return fmt.Errorf("failed to create directory for bundle: %w", err) - } - } +// Create creates a new bundle configuration in the current directory +func (p *Porter) Create() error { + destinationDir := "." + + if err := p.CopyTemplate(p.Templates.GetManifest, filepath.Join(destinationDir, config.Name)); err != nil { + return err } + return p.copyAllTemplatesExceptPorterYaml(destinationDir) +} + +// CreateInDir creates a new bundle configuration in the specified directory. The directory will be created if it +// doesn't already exist. For example, if dir is "foo/bar/baz", the directory structure "foo/bar/baz" will be created. +// The bundle name will be set to the "base" of the given directory, which is "baz" in the example above. +func (p *Porter) CreateInDir(dir string) error { + bundleName := filepath.Base(dir) - var err error - if bundleName == "" { - // create bundle with default name "porter_hello" - err = p.CopyTemplate(p.Templates.GetManifest, filepath.Join(bundleName, config.Name)) - } else { - // create bundle with given name - err = p.CopyTemplate(func() ([]byte, error) { - content, err := p.Templates.GetManifest() - if err != nil { - return nil, err - } - content = []byte(strings.ReplaceAll(string(content), "porter-hello", bundleName)) - return content, nil - }, filepath.Join(bundleName, config.Name)) + // Create dirs if they don't exist + _, err := os.Stat(dir) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + err = os.MkdirAll(dir, os.ModePerm) + } + if err != nil { + return fmt.Errorf("failed to create directory for bundle: %w", err) + } } + + // create porter.yaml, using base of given dir as the bundle name + err = p.CopyTemplate(func() ([]byte, error) { + content, err := p.Templates.GetManifest() + if err != nil { + return nil, err + } + content = []byte(strings.ReplaceAll(string(content), "porter-hello", bundleName)) + return content, nil + }, filepath.Join(dir, config.Name)) if err != nil { return err } - err = p.CopyTemplate(p.Templates.GetManifestHelpers, filepath.Join(bundleName, "helpers.sh")) + return p.copyAllTemplatesExceptPorterYaml(dir) +} + +func (p *Porter) copyAllTemplatesExceptPorterYaml(destinationDir string) error { + err := p.CopyTemplate(p.Templates.GetManifestHelpers, filepath.Join(destinationDir, "helpers.sh")) if err != nil { return err } - err = p.CopyTemplate(p.Templates.GetReadme, filepath.Join(bundleName, "README.md")) + err = p.CopyTemplate(p.Templates.GetReadme, filepath.Join(destinationDir, "README.md")) if err != nil { return err } - err = p.CopyTemplate(p.Templates.GetDockerfileTemplate, filepath.Join(bundleName, "template.Dockerfile")) + err = p.CopyTemplate(p.Templates.GetDockerfileTemplate, filepath.Join(destinationDir, "template.Dockerfile")) if err != nil { return err } - err = p.CopyTemplate(p.Templates.GetDockerignore, filepath.Join(bundleName, ".dockerignore")) + err = p.CopyTemplate(p.Templates.GetDockerignore, filepath.Join(destinationDir, ".dockerignore")) if err != nil { return err } - return p.CopyTemplate(p.Templates.GetGitignore, filepath.Join(bundleName, ".gitignore")) + return p.CopyTemplate(p.Templates.GetGitignore, filepath.Join(destinationDir, ".gitignore")) } func (p *Porter) CopyTemplate(getTemplate func() ([]byte, error), dest string) error { diff --git a/pkg/porter/create_test.go b/pkg/porter/create_test.go index 61589c247..22068d4a7 100644 --- a/pkg/porter/create_test.go +++ b/pkg/porter/create_test.go @@ -1,13 +1,12 @@ package porter import ( - "get.porter.sh/porter/pkg/manifest" - "get.porter.sh/porter/pkg/yaml" - "github.com/stretchr/testify/assert" "path/filepath" "testing" "get.porter.sh/porter/pkg" + "get.porter.sh/porter/pkg/manifest" + "get.porter.sh/porter/pkg/yaml" "get.porter.sh/porter/tests" "github.com/stretchr/testify/require" ) @@ -16,7 +15,7 @@ func TestCreateInWorkingDirectory(t *testing.T) { p := NewTestPorter(t) defer p.Close() - err := p.Create("") + err := p.Create() require.NoError(t, err) // Verify that files are present in the root directory @@ -50,7 +49,7 @@ func TestCreateWithBundleName(t *testing.T) { bundleName := "mybundle" p := NewTestPorter(t) - err := p.Create(bundleName) + err := p.Create() require.NoError(t, err) // Verify that files are present in the "mybundle" directory @@ -81,7 +80,7 @@ func TestCreateWithBundleName(t *testing.T) { // verify "name" inside porter.yaml is set to "mybundle" porterYaml := &manifest.Manifest{} data, err := p.FileSystem.ReadFile(filepath.Join(bundleName, "porter.yaml")) - assert.NoError(t, err) - assert.NoError(t, yaml.Unmarshal(data, &porterYaml)) - assert.True(t, porterYaml.Name == bundleName) + require.NoError(t, err) + require.NoError(t, yaml.Unmarshal(data, &porterYaml)) + require.True(t, porterYaml.Name == bundleName) } diff --git a/pkg/porter/lifecycle_test.go b/pkg/porter/lifecycle_test.go index 5859993fa..8d7926611 100644 --- a/pkg/porter/lifecycle_test.go +++ b/pkg/porter/lifecycle_test.go @@ -28,7 +28,7 @@ func TestInstallFromTagIgnoresCurrentBundle(t *testing.T) { p := NewTestPorter(t) defer p.Close() - err := p.Create("") + err := p.Create() require.NoError(t, err) installOpts := NewInstallOptions() diff --git a/tests/integration/invoke_test.go b/tests/integration/invoke_test.go index 16ff2f67f..e14907597 100644 --- a/tests/integration/invoke_test.go +++ b/tests/integration/invoke_test.go @@ -22,7 +22,7 @@ func TestInvokeCustomAction(t *testing.T) { ctx := p.SetupIntegrationTest() // Install a bundle with a custom action defined - err := p.Create("") + err := p.Create() require.NoError(t, err) bundleName := p.AddTestBundleDir("testdata/bundles/bundle-with-custom-action", true) diff --git a/tests/integration/outputs_test.go b/tests/integration/outputs_test.go index 4ee576cb8..6529b6956 100644 --- a/tests/integration/outputs_test.go +++ b/tests/integration/outputs_test.go @@ -79,7 +79,7 @@ func CleanupCurrentBundle(ctx context.Context, p *porter.TestPorter) { } func installExecOutputsBundle(ctx context.Context, p *porter.TestPorter) string { - err := p.Create("") + err := p.Create() require.NoError(p.T(), err) bundleName := p.AddTestBundleDir("testdata/bundles/exec-outputs", true) From 9a6666d3fa1438eb5a6bc0632b283a7c1605fcb8 Mon Sep 17 00:00:00 2001 From: Ludvig Liljenberg Date: Tue, 5 Sep 2023 14:46:00 -0700 Subject: [PATCH 09/13] fixed unittest Signed-off-by: Ludvig Liljenberg --- pkg/porter/create_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/porter/create_test.go b/pkg/porter/create_test.go index 22068d4a7..fa952a35a 100644 --- a/pkg/porter/create_test.go +++ b/pkg/porter/create_test.go @@ -49,7 +49,7 @@ func TestCreateWithBundleName(t *testing.T) { bundleName := "mybundle" p := NewTestPorter(t) - err := p.Create() + err := p.CreateInDir(bundleName) require.NoError(t, err) // Verify that files are present in the "mybundle" directory From f5c75d231c632dc253e945fac183b413033286a0 Mon Sep 17 00:00:00 2001 From: Ludvig Liljenberg Date: Tue, 5 Sep 2023 14:50:02 -0700 Subject: [PATCH 10/13] added test for nested name Signed-off-by: Ludvig Liljenberg --- pkg/porter/create_test.go | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/pkg/porter/create_test.go b/pkg/porter/create_test.go index fa952a35a..935b842a0 100644 --- a/pkg/porter/create_test.go +++ b/pkg/porter/create_test.go @@ -84,3 +84,45 @@ func TestCreateWithBundleName(t *testing.T) { require.NoError(t, yaml.Unmarshal(data, &porterYaml)) require.True(t, porterYaml.Name == bundleName) } + +// make sure bundlename is not the entire file structure, just the "base" +func TestCreateNestedBundleName(t *testing.T) { + dir := "foo/bar/bar" + bundleName := "mybundle" + + p := NewTestPorter(t) + err := p.CreateInDir(filepath.Join(dir, bundleName)) + require.NoError(t, err) + + // Verify that files are present in the "mybundle" directory + configFileStats, err := p.FileSystem.Stat(filepath.Join(bundleName, "porter.yaml")) + require.NoError(t, err) + tests.AssertFilePermissionsEqual(t, filepath.Join(bundleName, "porter.yaml"), pkg.FileModeWritable, configFileStats.Mode()) + + helperFileStats, err := p.FileSystem.Stat(filepath.Join(bundleName, "helpers.sh")) + require.NoError(t, err) + tests.AssertFilePermissionsEqual(t, filepath.Join(bundleName, "helpers.sh"), pkg.FileModeExecutable, helperFileStats.Mode()) + + dockerfileStats, err := p.FileSystem.Stat(filepath.Join(bundleName, "template.Dockerfile")) + require.NoError(t, err) + tests.AssertFilePermissionsEqual(t, filepath.Join(bundleName, "template.Dockerfile"), pkg.FileModeWritable, dockerfileStats.Mode()) + + readmeStats, err := p.FileSystem.Stat(filepath.Join(bundleName, "README.md")) + require.NoError(t, err) + tests.AssertFilePermissionsEqual(t, filepath.Join(bundleName, "README.md"), pkg.FileModeWritable, readmeStats.Mode()) + + gitignoreStats, err := p.FileSystem.Stat(filepath.Join(bundleName, ".gitignore")) + require.NoError(t, err) + tests.AssertFilePermissionsEqual(t, filepath.Join(bundleName, ".gitignore"), pkg.FileModeWritable, gitignoreStats.Mode()) + + dockerignoreStats, err := p.FileSystem.Stat(filepath.Join(bundleName, ".dockerignore")) + require.NoError(t, err) + tests.AssertFilePermissionsEqual(t, filepath.Join(bundleName, ".dockerignore"), pkg.FileModeWritable, dockerignoreStats.Mode()) + + // verify "name" inside porter.yaml is set to "mybundle" + porterYaml := &manifest.Manifest{} + data, err := p.FileSystem.ReadFile(filepath.Join(bundleName, "porter.yaml")) + require.NoError(t, err) + require.NoError(t, yaml.Unmarshal(data, &porterYaml)) + require.True(t, porterYaml.Name == bundleName) +} From bc4b1b0d659eff8c4aad1f531b691a5de99e3488 Mon Sep 17 00:00:00 2001 From: Ludvig Liljenberg Date: Tue, 5 Sep 2023 14:59:38 -0700 Subject: [PATCH 11/13] updated to use the porter io writer for stderr Signed-off-by: Ludvig Liljenberg --- pkg/porter/create.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/porter/create.go b/pkg/porter/create.go index 8e36068e6..f40f04c46 100644 --- a/pkg/porter/create.go +++ b/pkg/porter/create.go @@ -90,7 +90,7 @@ func (p *Porter) CopyTemplate(getTemplate func() ([]byte, error), dest string) e } if _, err := os.Stat(dest); err == nil { - fmt.Fprintf(os.Stderr, "WARNING: File %q already exists. Overwriting.\n", dest) + fmt.Fprintf(p.Err, "WARNING: File %q already exists. Overwriting.\n", dest) } err = p.FileSystem.WriteFile(dest, tmpl, mode) if err != nil { From a764dbdb8bc23778f0389c1ae4a0a2579bc6f361 Mon Sep 17 00:00:00 2001 From: Ludvig Liljenberg Date: Tue, 5 Sep 2023 15:51:41 -0700 Subject: [PATCH 12/13] fixed perm code + test Signed-off-by: Ludvig Liljenberg --- pkg/porter/create.go | 2 +- pkg/porter/create_test.go | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/pkg/porter/create.go b/pkg/porter/create.go index f40f04c46..aa527b3f2 100644 --- a/pkg/porter/create.go +++ b/pkg/porter/create.go @@ -31,7 +31,7 @@ func (p *Porter) CreateInDir(dir string) error { _, err := os.Stat(dir) if err != nil { if errors.Is(err, os.ErrNotExist) { - err = os.MkdirAll(dir, os.ModePerm) + err = os.MkdirAll(dir, 0755) } if err != nil { return fmt.Errorf("failed to create directory for bundle: %w", err) diff --git a/pkg/porter/create_test.go b/pkg/porter/create_test.go index 935b842a0..8eb75390c 100644 --- a/pkg/porter/create_test.go +++ b/pkg/porter/create_test.go @@ -95,33 +95,33 @@ func TestCreateNestedBundleName(t *testing.T) { require.NoError(t, err) // Verify that files are present in the "mybundle" directory - configFileStats, err := p.FileSystem.Stat(filepath.Join(bundleName, "porter.yaml")) + configFileStats, err := p.FileSystem.Stat(filepath.Join(dir, bundleName, "porter.yaml")) require.NoError(t, err) - tests.AssertFilePermissionsEqual(t, filepath.Join(bundleName, "porter.yaml"), pkg.FileModeWritable, configFileStats.Mode()) + tests.AssertFilePermissionsEqual(t, filepath.Join(dir, bundleName, "porter.yaml"), pkg.FileModeWritable, configFileStats.Mode()) - helperFileStats, err := p.FileSystem.Stat(filepath.Join(bundleName, "helpers.sh")) + helperFileStats, err := p.FileSystem.Stat(filepath.Join(dir, bundleName, "helpers.sh")) require.NoError(t, err) - tests.AssertFilePermissionsEqual(t, filepath.Join(bundleName, "helpers.sh"), pkg.FileModeExecutable, helperFileStats.Mode()) + tests.AssertFilePermissionsEqual(t, filepath.Join(dir, bundleName, "helpers.sh"), pkg.FileModeExecutable, helperFileStats.Mode()) - dockerfileStats, err := p.FileSystem.Stat(filepath.Join(bundleName, "template.Dockerfile")) + dockerfileStats, err := p.FileSystem.Stat(filepath.Join(dir, bundleName, "template.Dockerfile")) require.NoError(t, err) - tests.AssertFilePermissionsEqual(t, filepath.Join(bundleName, "template.Dockerfile"), pkg.FileModeWritable, dockerfileStats.Mode()) + tests.AssertFilePermissionsEqual(t, filepath.Join(dir, bundleName, "template.Dockerfile"), pkg.FileModeWritable, dockerfileStats.Mode()) - readmeStats, err := p.FileSystem.Stat(filepath.Join(bundleName, "README.md")) + readmeStats, err := p.FileSystem.Stat(filepath.Join(dir, bundleName, "README.md")) require.NoError(t, err) - tests.AssertFilePermissionsEqual(t, filepath.Join(bundleName, "README.md"), pkg.FileModeWritable, readmeStats.Mode()) + tests.AssertFilePermissionsEqual(t, filepath.Join(dir, bundleName, "README.md"), pkg.FileModeWritable, readmeStats.Mode()) - gitignoreStats, err := p.FileSystem.Stat(filepath.Join(bundleName, ".gitignore")) + gitignoreStats, err := p.FileSystem.Stat(filepath.Join(dir, bundleName, ".gitignore")) require.NoError(t, err) - tests.AssertFilePermissionsEqual(t, filepath.Join(bundleName, ".gitignore"), pkg.FileModeWritable, gitignoreStats.Mode()) + tests.AssertFilePermissionsEqual(t, filepath.Join(dir, bundleName, ".gitignore"), pkg.FileModeWritable, gitignoreStats.Mode()) - dockerignoreStats, err := p.FileSystem.Stat(filepath.Join(bundleName, ".dockerignore")) + dockerignoreStats, err := p.FileSystem.Stat(filepath.Join(dir, bundleName, ".dockerignore")) require.NoError(t, err) - tests.AssertFilePermissionsEqual(t, filepath.Join(bundleName, ".dockerignore"), pkg.FileModeWritable, dockerignoreStats.Mode()) + tests.AssertFilePermissionsEqual(t, filepath.Join(dir, bundleName, ".dockerignore"), pkg.FileModeWritable, dockerignoreStats.Mode()) // verify "name" inside porter.yaml is set to "mybundle" porterYaml := &manifest.Manifest{} - data, err := p.FileSystem.ReadFile(filepath.Join(bundleName, "porter.yaml")) + data, err := p.FileSystem.ReadFile(filepath.Join(dir, bundleName, "porter.yaml")) require.NoError(t, err) require.NoError(t, yaml.Unmarshal(data, &porterYaml)) require.True(t, porterYaml.Name == bundleName) From dbfac3b704c6bc5cf6779f60ed360a5e8b3a6c7a Mon Sep 17 00:00:00 2001 From: Ludvig Liljenberg Date: Tue, 5 Sep 2023 16:36:40 -0700 Subject: [PATCH 13/13] feedback Signed-off-by: Ludvig Liljenberg --- pkg/porter/create.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/pkg/porter/create.go b/pkg/porter/create.go index aa527b3f2..7a8c61eb5 100644 --- a/pkg/porter/create.go +++ b/pkg/porter/create.go @@ -13,7 +13,7 @@ import ( // Create creates a new bundle configuration in the current directory func (p *Porter) Create() error { - destinationDir := "." + destinationDir := "." // current directory if err := p.CopyTemplate(p.Templates.GetManifest, filepath.Join(destinationDir, config.Name)); err != nil { return err @@ -28,14 +28,13 @@ func (p *Porter) CreateInDir(dir string) error { bundleName := filepath.Base(dir) // Create dirs if they don't exist - _, err := os.Stat(dir) + _, err := p.FileSystem.Stat(dir) + if errors.Is(err, os.ErrNotExist) { + err = p.FileSystem.MkdirAll(dir, 0755) + } if err != nil { - if errors.Is(err, os.ErrNotExist) { - err = os.MkdirAll(dir, 0755) - } - if err != nil { - return fmt.Errorf("failed to create directory for bundle: %w", err) - } + // the Stat failed with an error different from os.ErrNotExist OR the MkdirAll failed to create the dir(s) + return fmt.Errorf("failed to create directory for bundle: %w", err) } // create porter.yaml, using base of given dir as the bundle name @@ -89,7 +88,7 @@ func (p *Porter) CopyTemplate(getTemplate func() ([]byte, error), dest string) e mode = pkg.FileModeExecutable } - if _, err := os.Stat(dest); err == nil { + if _, err := p.FileSystem.Stat(dest); err == nil { fmt.Fprintf(p.Err, "WARNING: File %q already exists. Overwriting.\n", dest) } err = p.FileSystem.WriteFile(dest, tmpl, mode)