From 01e70d501b7ff926ccb3a3ca0281fc00d1777f47 Mon Sep 17 00:00:00 2001 From: Tadayoshi Sato Date: Thu, 28 Jul 2022 13:14:12 +0900 Subject: [PATCH 1/9] chore(cli): refactor kamel local cmds --- e2e/namespace/install/cli/dev_mode_test.go | 2 +- pkg/cmd/local_build.go | 54 +++++++++--------- pkg/cmd/local_inspect.go | 14 ++--- pkg/cmd/local_run.go | 64 +++++++++++----------- pkg/cmd/local_util.go | 1 + 5 files changed, 68 insertions(+), 67 deletions(-) diff --git a/e2e/namespace/install/cli/dev_mode_test.go b/e2e/namespace/install/cli/dev_mode_test.go index dd808e2c53..289af36972 100644 --- a/e2e/namespace/install/cli/dev_mode_test.go +++ b/e2e/namespace/install/cli/dev_mode_test.go @@ -28,9 +28,9 @@ import ( "io" "io/ioutil" "os" + "path/filepath" "testing" "time" - "path/filepath" . "github.com/onsi/gomega" "github.com/stretchr/testify/assert" diff --git a/pkg/cmd/local_build.go b/pkg/cmd/local_build.go index 5c0d72cd40..2bbb4b3f53 100644 --- a/pkg/cmd/local_build.go +++ b/pkg/cmd/local_build.go @@ -81,7 +81,7 @@ type localBuildCmdOptions struct { MavenRepositories []string `mapstructure:"maven-repositories"` } -func (command *localBuildCmdOptions) validate(args []string) error { +func (o *localBuildCmdOptions) validate(args []string) error { // Validate integration files. if len(args) > 0 { if err := validateIntegrationFiles(args); err != nil { @@ -90,51 +90,51 @@ func (command *localBuildCmdOptions) validate(args []string) error { } // Validate additional dependencies specified by the user. - if err := validateDependencies(command.Dependencies); err != nil { + if err := validateDependencies(o.Dependencies); err != nil { return err } // Validate properties file. - if err := validateFiles(command.PropertyFiles); err != nil { + if err := validateFiles(o.PropertyFiles); err != nil { return err } - if command.BaseImage { + if o.BaseImage { // Cannot have both integration files and the base image construction enabled. if len(args) > 0 { return errors.New("integration files have been provided and the base image construction is enabled") } // Docker registry must be set. - if command.ContainerRegistry == "" { + if o.ContainerRegistry == "" { return errors.New("base image cannot be built because container registry has not been provided") } // If an integration directory is provided then no base image containerization can be enabled. - if command.IntegrationDirectory != "" { + if o.IntegrationDirectory != "" { return errors.New("base image construction does not use integration files") } - } else if command.ContainerRegistry != "" { + } else if o.ContainerRegistry != "" { // ContainerRegistry should only be specified when building the base image. return errors.New("cannot specify container registry unless a base integration image is being built") } // The integration directory must be set when only outputting dependencies. - if command.DependenciesOnly && command.IntegrationDirectory == "" { + if o.DependenciesOnly && o.IntegrationDirectory == "" { return errors.New("to output dependencies the integration directory flag must be set") } return nil } -func (command *localBuildCmdOptions) init(args []string) error { +func (o *localBuildCmdOptions) init(args []string) error { // Create integration directory if one is provided. - err := util.CreateDirectory(command.IntegrationDirectory) + err := util.CreateDirectory(o.IntegrationDirectory) if err != nil { return err } - if command.BaseImage || command.Image != "" { + if o.BaseImage || o.Image != "" { // If base image construction is enabled create a directory for it. err := createDockerBaseWorkingDirectory() if err != nil { @@ -142,7 +142,7 @@ func (command *localBuildCmdOptions) init(args []string) error { } // If integration image construction is enabled, an integration image will be built. - if command.Image != "" { + if o.Image != "" { err := createDockerWorkingDirectory() if err != nil { return err @@ -158,19 +158,19 @@ func (command *localBuildCmdOptions) init(args []string) error { return nil } -func (command *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { +func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { var dependenciesList, propertyFilesList []string routeFiles := args - if !command.BaseImage { - dependencies, err := GetDependencies(command.Context, args, command.Dependencies, command.MavenRepositories, true) + if !o.BaseImage { + dependencies, err := GetDependencies(o.Context, args, o.Dependencies, o.MavenRepositories, true) if err != nil { return err } var propertyFiles []string - if !command.DependenciesOnly { + if !o.DependenciesOnly { // Manage integration properties which may come from files or CLI - propertyFiles, err = updateIntegrationProperties(command.Properties, command.PropertyFiles, false) + propertyFiles, err = updateIntegrationProperties(o.Properties, o.PropertyFiles, false) if err != nil { return err } @@ -178,10 +178,10 @@ func (command *localBuildCmdOptions) run(cmd *cobra.Command, args []string) erro dependenciesList = dependencies propertyFilesList = propertyFiles - hasIntegrationDir := command.IntegrationDirectory != "" + hasIntegrationDir := o.IntegrationDirectory != "" if hasIntegrationDir { // Create dependencies subdirectory. - localDependenciesDirectory := getCustomDependenciesDir(command.IntegrationDirectory) + localDependenciesDirectory := getCustomDependenciesDir(o.IntegrationDirectory) // Copy dependencies in persistent IntegrationDirectory/dependencies dependenciesList, err = util.CopyIntegrationFilesToDirectory(dependencies, localDependenciesDirectory) @@ -190,12 +190,12 @@ func (command *localBuildCmdOptions) run(cmd *cobra.Command, args []string) erro } // Once dependencies have been copied to local folder, we can exit. - if command.DependenciesOnly { + if o.DependenciesOnly { return nil } // Create dependencies subdirectory. - localPropertiesDirectory := getCustomPropertiesDir(command.IntegrationDirectory) + localPropertiesDirectory := getCustomPropertiesDir(o.IntegrationDirectory) // Copy dependencies in persistent IntegrationDirectory/dependencies propertyFilesList, err = util.CopyIntegrationFilesToDirectory(propertyFiles, localPropertiesDirectory) @@ -204,7 +204,7 @@ func (command *localBuildCmdOptions) run(cmd *cobra.Command, args []string) erro } // Save routes. - localRoutesDirectory := getCustomRoutesDir(command.IntegrationDirectory) + localRoutesDirectory := getCustomRoutesDir(o.IntegrationDirectory) // Copy routes in persistent IntegrationDirectory/dependencies routeFiles, err = util.CopyIntegrationFilesToDirectory(args, localRoutesDirectory) @@ -220,13 +220,13 @@ func (command *localBuildCmdOptions) run(cmd *cobra.Command, args []string) erro // The only case in which we should not execute the integration image creation is when we want to // just output the files that comprise the integration locally. - if command.IntegrationDirectory != "" && command.Image == "" { + if o.IntegrationDirectory != "" && o.Image == "" { return nil } // Create and build integration image. - err := createAndBuildIntegrationImage(command.Context, command.ContainerRegistry, command.BaseImage, - command.Image, propertyFilesList, dependenciesList, routeFiles, false, cmd.OutOrStdout(), cmd.ErrOrStderr()) + err := createAndBuildIntegrationImage(o.Context, o.ContainerRegistry, o.BaseImage, + o.Image, propertyFilesList, dependenciesList, routeFiles, false, cmd.OutOrStdout(), cmd.ErrOrStderr()) if err != nil { return err } @@ -234,7 +234,7 @@ func (command *localBuildCmdOptions) run(cmd *cobra.Command, args []string) erro return nil } -func (command *localBuildCmdOptions) deinit() error { +func (o *localBuildCmdOptions) deinit() error { // If base image construction is enabled delete the directory for it. err := deleteDockerBaseWorkingDirectory() if err != nil { @@ -242,7 +242,7 @@ func (command *localBuildCmdOptions) deinit() error { } // If integration files are provided delete the maven project folder. - if !command.BaseImage { + if !o.BaseImage { err = deleteDockerWorkingDirectory() if err != nil { return err diff --git a/pkg/cmd/local_inspect.go b/pkg/cmd/local_inspect.go index 54fca9862f..f5e523bc17 100644 --- a/pkg/cmd/local_inspect.go +++ b/pkg/cmd/local_inspect.go @@ -70,29 +70,29 @@ type localInspectCmdOptions struct { MavenRepositories []string `mapstructure:"maven-repositories"` } -func (command *localInspectCmdOptions) validate(args []string) error { +func (o *localInspectCmdOptions) validate(args []string) error { if err := validateIntegrationFiles(args); err != nil { return err } - if err := validateDependencies(command.Dependencies); err != nil { + if err := validateDependencies(o.Dependencies); err != nil { return err } return nil } -func (command *localInspectCmdOptions) init() error { +func (o *localInspectCmdOptions) init() error { return createMavenWorkingDirectory() } -func (command *localInspectCmdOptions) run(cmd *cobra.Command, args []string) error { - dependencies, err := GetDependencies(command.Context, args, command.Dependencies, command.MavenRepositories, command.AllDependencies) +func (o *localInspectCmdOptions) run(cmd *cobra.Command, args []string) error { + dependencies, err := GetDependencies(o.Context, args, o.Dependencies, o.MavenRepositories, o.AllDependencies) if err != nil { return err } - err = outputDependencies(dependencies, command.OutputFormat, cmd) + err = outputDependencies(dependencies, o.OutputFormat, cmd) if err != nil { return err } @@ -100,6 +100,6 @@ func (command *localInspectCmdOptions) run(cmd *cobra.Command, args []string) er return nil } -func (command *localInspectCmdOptions) deinit() error { +func (o *localInspectCmdOptions) deinit() error { return deleteMavenWorkingDirectory() } diff --git a/pkg/cmd/local_run.go b/pkg/cmd/local_run.go index ec021ed0d2..024a361a38 100644 --- a/pkg/cmd/local_run.go +++ b/pkg/cmd/local_run.go @@ -97,35 +97,35 @@ type localRunCmdOptions struct { MavenRepositories []string `mapstructure:"maven-repositories"` } -func (command *localRunCmdOptions) validate(args []string) error { +func (o *localRunCmdOptions) validate(args []string) error { // Validate integration files when no image is provided and we are // not running an already locally-built integration. - if command.Image == "" && command.IntegrationDirectory == "" { + if o.Image == "" && o.IntegrationDirectory == "" { if err := validateIntegrationFiles(args); err != nil { return err } } // Validate additional dependencies specified by the user. - if err := validateDependencies(command.Dependencies); err != nil { + if err := validateDependencies(o.Dependencies); err != nil { return err } // Validate properties file. - if err := validatePropertyFiles(command.PropertyFiles); err != nil { + if err := validatePropertyFiles(o.PropertyFiles); err != nil { return err } // If containerize is set then docker image name must be set. - if command.Containerize && command.Image == "" { + if o.Containerize && o.Image == "" { return errors.New("containerization is active but no image name has been provided") } return nil } -func (command *localRunCmdOptions) init() error { - if command.Containerize { +func (o *localRunCmdOptions) init() error { + if o.Containerize { if err := createDockerBaseWorkingDirectory(); err != nil { return err } @@ -135,42 +135,42 @@ func (command *localRunCmdOptions) init() error { } } - setDockerNetworkName(command.Network) + setDockerNetworkName(o.Network) - setDockerEnvVars(command.EnvironmentVariables) + setDockerEnvVars(o.EnvironmentVariables) return createMavenWorkingDirectory() } -func (command *localRunCmdOptions) run(cmd *cobra.Command, args []string) error { +func (o *localRunCmdOptions) run(cmd *cobra.Command, args []string) error { // If local run is provided with an image name, it will just run the image locally and exit. - if command.Image != "" && !command.Containerize { + if o.Image != "" && !o.Containerize { // Run image locally. - if err := runIntegrationImage(command.Context, command.Image, cmd.OutOrStdout(), cmd.ErrOrStderr()); err != nil { + if err := runIntegrationImage(o.Context, o.Image, cmd.OutOrStdout(), cmd.ErrOrStderr()); err != nil { return err } return nil } - hasIntegrationDir := command.IntegrationDirectory != "" + hasIntegrationDir := o.IntegrationDirectory != "" var dependencies []string if hasIntegrationDir { // Fetch local dependencies - localBuildDependencies, err := getLocalBuildDependencies(command.IntegrationDirectory) + localBuildDependencies, err := getLocalBuildDependencies(o.IntegrationDirectory) if err != nil { return err } dependencies = localBuildDependencies // Local dependencies directory - localDependenciesDirectory := getCustomDependenciesDir(command.IntegrationDirectory) + localDependenciesDirectory := getCustomDependenciesDir(o.IntegrationDirectory) // The quarkus application files need to be at a specific location i.e.: // /../quarkus/quarkus-application.dat // /../quarkus/generated-bytecode.jar - localQuarkusDir := getCustomQuarkusDir(command.IntegrationDirectory) + localQuarkusDir := getCustomQuarkusDir(o.IntegrationDirectory) err = util.CopyQuarkusAppFiles(localDependenciesDirectory, localQuarkusDir) if err != nil { return err @@ -178,7 +178,7 @@ func (command *localRunCmdOptions) run(cmd *cobra.Command, args []string) error // The dependency jar files need to be at a specific location i.e.: // /../lib/main/*.jar - localLibDirectory := getCustomLibDir(command.IntegrationDirectory) + localLibDirectory := getCustomLibDir(o.IntegrationDirectory) err = util.CopyLibFiles(localDependenciesDirectory, localLibDirectory) if err != nil { return err @@ -186,13 +186,13 @@ func (command *localRunCmdOptions) run(cmd *cobra.Command, args []string) error // The Camel K jar file needs to be at a specific location i.e.: // /../app/camel-k-integration-X.X.X{-SNAPSHOT}.jar - localAppDirectory := getCustomAppDir(command.IntegrationDirectory) + localAppDirectory := getCustomAppDir(o.IntegrationDirectory) err = util.CopyAppFile(localDependenciesDirectory, localAppDirectory) if err != nil { return err } } else { - computedDependencies, err := GetDependencies(command.Context, args, command.Dependencies, command.MavenRepositories, true) + computedDependencies, err := GetDependencies(o.Context, args, o.Dependencies, o.MavenRepositories, true) if err != nil { return err } @@ -200,16 +200,16 @@ func (command *localRunCmdOptions) run(cmd *cobra.Command, args []string) error } // Manage integration properties which may come from files or CLI. - propertyFiles := command.PropertyFiles + propertyFiles := o.PropertyFiles if hasIntegrationDir { - localBuildPropertyFiles, err := getLocalBuildProperties(command.IntegrationDirectory) + localBuildPropertyFiles, err := getLocalBuildProperties(o.IntegrationDirectory) if err != nil { return err } propertyFiles = localBuildPropertyFiles } - updatedPropertyFiles, err := updateIntegrationProperties(command.Properties, propertyFiles, hasIntegrationDir) + updatedPropertyFiles, err := updateIntegrationProperties(o.Properties, propertyFiles, hasIntegrationDir) if err != nil { return err } @@ -217,7 +217,7 @@ func (command *localRunCmdOptions) run(cmd *cobra.Command, args []string) error routes := args if hasIntegrationDir { - localBuildRoutes, err := getLocalBuildRoutes(command.IntegrationDirectory) + localBuildRoutes, err := getLocalBuildRoutes(o.IntegrationDirectory) if err != nil { return err } @@ -225,26 +225,26 @@ func (command *localRunCmdOptions) run(cmd *cobra.Command, args []string) error } // If this is a containerized local run, create, build and run the container image. - if command.Containerize { + if o.Containerize { // Create and build integration image. - err := createAndBuildIntegrationImage(command.Context, "", false, command.Image, propertyFiles, dependencies, routes, hasIntegrationDir, cmd.OutOrStdout(), cmd.ErrOrStderr()) + err := createAndBuildIntegrationImage(o.Context, "", false, o.Image, propertyFiles, dependencies, routes, hasIntegrationDir, cmd.OutOrStdout(), cmd.ErrOrStderr()) if err != nil { return err } // Run integration image. - err = runIntegrationImage(command.Context, command.Image, cmd.OutOrStdout(), cmd.ErrOrStderr()) + err = runIntegrationImage(o.Context, o.Image, cmd.OutOrStdout(), cmd.ErrOrStderr()) if err != nil { return err } } else { propertiesDir := util.GetLocalPropertiesDir() if hasIntegrationDir { - propertiesDir = getCustomPropertiesDir(command.IntegrationDirectory) + propertiesDir = getCustomPropertiesDir(o.IntegrationDirectory) } // Run integration locally. - err := RunLocalIntegrationRunCommand(command.Context, propertyFiles, dependencies, routes, propertiesDir, cmd.OutOrStdout(), cmd.ErrOrStderr()) + err := RunLocalIntegrationRunCommand(o.Context, propertyFiles, dependencies, routes, propertiesDir, cmd.OutOrStdout(), cmd.ErrOrStderr()) if err != nil { return err } @@ -253,8 +253,8 @@ func (command *localRunCmdOptions) run(cmd *cobra.Command, args []string) error return nil } -func (command *localRunCmdOptions) deinit() error { - if command.Containerize { +func (o *localRunCmdOptions) deinit() error { + if o.Containerize { err := deleteDockerBaseWorkingDirectory() if err != nil { return err @@ -266,8 +266,8 @@ func (command *localRunCmdOptions) deinit() error { } } - if command.IntegrationDirectory != "" { - err := deleteLocalIntegrationDirs(command.IntegrationDirectory) + if o.IntegrationDirectory != "" { + err := deleteLocalIntegrationDirs(o.IntegrationDirectory) if err != nil { return err } diff --git a/pkg/cmd/local_util.go b/pkg/cmd/local_util.go index c9b04feda6..75837d85f3 100644 --- a/pkg/cmd/local_util.go +++ b/pkg/cmd/local_util.go @@ -280,6 +280,7 @@ func validateFile(file string) error { return nil } +// validateFiles ensures existence of given files. func validateFiles(args []string) error { // Ensure source files exist for _, arg := range args { From b7c3ab06eb65db9fde461ed58395532880eb2615 Mon Sep 17 00:00:00 2001 From: Tadayoshi Sato Date: Thu, 28 Jul 2022 15:35:34 +0900 Subject: [PATCH 2/9] chore(cli): further refactor kamel local cmds --- pkg/cmd/local.go | 3 +- pkg/cmd/local_build.go | 37 ++--- pkg/cmd/local_run.go | 6 +- pkg/cmd/local_util.go | 121 ++++++++++++++- ...inerization.go => local_util_container.go} | 24 +-- pkg/util/util.go | 141 ++---------------- 6 files changed, 160 insertions(+), 172 deletions(-) rename pkg/cmd/{util_containerization.go => local_util_container.go} (92%) diff --git a/pkg/cmd/local.go b/pkg/cmd/local.go index 1a480490f6..65163bfa51 100644 --- a/pkg/cmd/local.go +++ b/pkg/cmd/local.go @@ -75,6 +75,7 @@ func (o *LocalCmdOptions) persistentPreRun(cmd *cobra.Command, args []string) er func warnTraitUsages(cmd *cobra.Command, traits []string) { if len(traits) > 0 { - fmt.Fprintf(cmd.OutOrStdout(), "Warning: traits are specified but don't take effect for local run: %v\n", traits) + fmt.Fprintf(cmd.OutOrStdout(), + "Warning: traits are specified but don't take effect for local run: %v\n", traits) } } diff --git a/pkg/cmd/local_build.go b/pkg/cmd/local_build.go index 2bbb4b3f53..079bf0dc38 100644 --- a/pkg/cmd/local_build.go +++ b/pkg/cmd/local_build.go @@ -129,29 +129,27 @@ func (o *localBuildCmdOptions) validate(args []string) error { func (o *localBuildCmdOptions) init(args []string) error { // Create integration directory if one is provided. - err := util.CreateDirectory(o.IntegrationDirectory) - if err != nil { - return err + if o.IntegrationDirectory != "" { + if err := util.CreateDirectory(o.IntegrationDirectory); err != nil { + return err + } } if o.BaseImage || o.Image != "" { // If base image construction is enabled create a directory for it. - err := createDockerBaseWorkingDirectory() - if err != nil { + if err := createDockerBaseWorkingDirectory(); err != nil { return err } // If integration image construction is enabled, an integration image will be built. if o.Image != "" { - err := createDockerWorkingDirectory() - if err != nil { + if err := createDockerWorkingDirectory(); err != nil { return err } } } - err = createMavenWorkingDirectory() - if err != nil { + if err := createMavenWorkingDirectory(); err != nil { return err } @@ -178,13 +176,12 @@ func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { dependenciesList = dependencies propertyFilesList = propertyFiles - hasIntegrationDir := o.IntegrationDirectory != "" - if hasIntegrationDir { + if o.IntegrationDirectory != "" { // Create dependencies subdirectory. localDependenciesDirectory := getCustomDependenciesDir(o.IntegrationDirectory) // Copy dependencies in persistent IntegrationDirectory/dependencies - dependenciesList, err = util.CopyIntegrationFilesToDirectory(dependencies, localDependenciesDirectory) + dependenciesList, err = CopyIntegrationFilesToDirectory(dependencies, localDependenciesDirectory) if err != nil { return err } @@ -198,7 +195,7 @@ func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { localPropertiesDirectory := getCustomPropertiesDir(o.IntegrationDirectory) // Copy dependencies in persistent IntegrationDirectory/dependencies - propertyFilesList, err = util.CopyIntegrationFilesToDirectory(propertyFiles, localPropertiesDirectory) + propertyFilesList, err = CopyIntegrationFilesToDirectory(propertyFiles, localPropertiesDirectory) if err != nil { return err } @@ -207,7 +204,7 @@ func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { localRoutesDirectory := getCustomRoutesDir(o.IntegrationDirectory) // Copy routes in persistent IntegrationDirectory/dependencies - routeFiles, err = util.CopyIntegrationFilesToDirectory(args, localRoutesDirectory) + routeFiles, err = CopyIntegrationFilesToDirectory(args, localRoutesDirectory) if err != nil { return err } @@ -226,7 +223,8 @@ func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { // Create and build integration image. err := createAndBuildIntegrationImage(o.Context, o.ContainerRegistry, o.BaseImage, - o.Image, propertyFilesList, dependenciesList, routeFiles, false, cmd.OutOrStdout(), cmd.ErrOrStderr()) + o.Image, propertyFilesList, dependenciesList, routeFiles, false, + cmd.OutOrStdout(), cmd.ErrOrStderr()) if err != nil { return err } @@ -236,19 +234,16 @@ func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { func (o *localBuildCmdOptions) deinit() error { // If base image construction is enabled delete the directory for it. - err := deleteDockerBaseWorkingDirectory() - if err != nil { + if err := deleteDockerBaseWorkingDirectory(); err != nil { return err } // If integration files are provided delete the maven project folder. if !o.BaseImage { - err = deleteDockerWorkingDirectory() - if err != nil { + if err := deleteDockerWorkingDirectory(); err != nil { return err } - err = deleteMavenWorkingDirectory() - if err != nil { + if err := deleteMavenWorkingDirectory(); err != nil { return err } } diff --git a/pkg/cmd/local_run.go b/pkg/cmd/local_run.go index 024a361a38..ad6f77ce3a 100644 --- a/pkg/cmd/local_run.go +++ b/pkg/cmd/local_run.go @@ -171,7 +171,7 @@ func (o *localRunCmdOptions) run(cmd *cobra.Command, args []string) error { // /../quarkus/quarkus-application.dat // /../quarkus/generated-bytecode.jar localQuarkusDir := getCustomQuarkusDir(o.IntegrationDirectory) - err = util.CopyQuarkusAppFiles(localDependenciesDirectory, localQuarkusDir) + err = CopyQuarkusAppFiles(localDependenciesDirectory, localQuarkusDir) if err != nil { return err } @@ -179,7 +179,7 @@ func (o *localRunCmdOptions) run(cmd *cobra.Command, args []string) error { // The dependency jar files need to be at a specific location i.e.: // /../lib/main/*.jar localLibDirectory := getCustomLibDir(o.IntegrationDirectory) - err = util.CopyLibFiles(localDependenciesDirectory, localLibDirectory) + err = CopyLibFiles(localDependenciesDirectory, localLibDirectory) if err != nil { return err } @@ -187,7 +187,7 @@ func (o *localRunCmdOptions) run(cmd *cobra.Command, args []string) error { // The Camel K jar file needs to be at a specific location i.e.: // /../app/camel-k-integration-X.X.X{-SNAPSHOT}.jar localAppDirectory := getCustomAppDir(o.IntegrationDirectory) - err = util.CopyAppFile(localDependenciesDirectory, localAppDirectory) + err = CopyAppFile(localDependenciesDirectory, localAppDirectory) if err != nil { return err } diff --git a/pkg/cmd/local_util.go b/pkg/cmd/local_util.go index 75837d85f3..3ecd9adc79 100644 --- a/pkg/cmd/local_util.go +++ b/pkg/cmd/local_util.go @@ -427,7 +427,7 @@ func updateQuarkusDirectory() error { } // ignore error if custom dir doesn't exist - _ = util.CopyQuarkusAppFiles(util.CustomQuarkusDirectoryName, util.GetLocalQuarkusDir()) + _ = CopyQuarkusAppFiles(util.CustomQuarkusDirectoryName, util.GetLocalQuarkusDir()) return nil } @@ -439,7 +439,7 @@ func updateAppDirectory() error { } // ignore error if custom dir doesn't exist - _ = util.CopyAppFile(util.CustomAppDirectoryName, util.GetLocalAppDir()) + _ = CopyAppFile(util.CustomAppDirectoryName, util.GetLocalAppDir()) return nil } @@ -451,7 +451,7 @@ func updateLibDirectory() error { } // ignore error if custom dir doesn't exist - _ = util.CopyLibFiles(util.CustomLibDirectoryName, util.GetLocalLibDir()) + _ = CopyLibFiles(util.CustomLibDirectoryName, util.GetLocalLibDir()) return nil } @@ -517,3 +517,118 @@ func deleteLocalIntegrationDirs(integrationDirectory string) error { return nil } + +func CopyIntegrationFilesToDirectory(files []string, directory string) ([]string, error) { + // Create directory if one does not already exist + if err := util.CreateDirectory(directory); err != nil { + return nil, err + } + + // Copy files to new location. Also create the list with relocated files. + relocatedFilesList := []string{} + for _, filePath := range files { + newFilePath := path.Join(directory, path.Base(filePath)) + _, err := util.CopyFile(filePath, newFilePath) + if err != nil { + return relocatedFilesList, err + } + relocatedFilesList = append(relocatedFilesList, newFilePath) + } + + return relocatedFilesList, nil +} + +func CopyQuarkusAppFiles(localDependenciesDirectory string, localQuarkusDir string) error { + // Create directory if one does not already exist + err := util.CreateDirectory(localQuarkusDir) + if err != nil { + return err + } + + // Transfer all files with a .dat extension and all files with a *-bytecode.jar suffix. + files, err := getRegularFileNamesInDir(localDependenciesDirectory) + if err != nil { + return err + } + for _, file := range files { + if strings.HasSuffix(file, ".dat") || strings.HasSuffix(file, "-bytecode.jar") { + source := path.Join(localDependenciesDirectory, file) + destination := path.Join(localQuarkusDir, file) + _, err = util.CopyFile(source, destination) + if err != nil { + return err + } + } + } + + return nil +} + +func CopyLibFiles(localDependenciesDirectory string, localLibDirectory string) error { + // Create directory if one does not already exist + err := util.CreateDirectory(localLibDirectory) + if err != nil { + return err + } + + fileNames, err := getRegularFileNamesInDir(localDependenciesDirectory) + if err != nil { + return err + } + + for _, dependencyJar := range fileNames { + source := path.Join(localDependenciesDirectory, dependencyJar) + destination := path.Join(localLibDirectory, dependencyJar) + _, err = util.CopyFile(source, destination) + if err != nil { + return err + } + } + + return nil +} + +func CopyAppFile(localDependenciesDirectory string, localAppDirectory string) error { + // Create directory if one does not already exist + err := util.CreateDirectory(localAppDirectory) + if err != nil { + return err + } + + fileNames, err := getRegularFileNamesInDir(localDependenciesDirectory) + if err != nil { + return err + } + + for _, dependencyJar := range fileNames { + if strings.HasPrefix(dependencyJar, "camel-k-integration-") { + source := path.Join(localDependenciesDirectory, dependencyJar) + destination := path.Join(localAppDirectory, dependencyJar) + _, err = util.CopyFile(source, destination) + if err != nil { + return err + } + } + } + + return nil +} + +func getRegularFileNamesInDir(directory string) ([]string, error) { + var dirFiles []string + files, err := ioutil.ReadDir(directory) + for _, file := range files { + fileName := file.Name() + + // Do not include hidden files or sub-directories. + if !file.IsDir() && !strings.HasPrefix(fileName, ".") { + dirFiles = append(dirFiles, fileName) + } + } + + if err != nil { + return nil, err + } + + return dirFiles, nil +} diff --git a/pkg/cmd/util_containerization.go b/pkg/cmd/local_util_container.go similarity index 92% rename from pkg/cmd/util_containerization.go rename to pkg/cmd/local_util_container.go index ec1c2e9327..64e9dd886b 100644 --- a/pkg/cmd/util_containerization.go +++ b/pkg/cmd/local_util_container.go @@ -85,8 +85,7 @@ func setDockerEnvVars(envVars []string) { func createAndBuildBaseImage(ctx context.Context, stdout, stderr io.Writer) error { // Create the base image Docker file. - err := docker.CreateBaseImageDockerFile() - if err != nil { + if err := docker.CreateBaseImageDockerFile(); err != nil { return err } @@ -130,8 +129,7 @@ func createAndBuildIntegrationImage(ctx context.Context, containerRegistry strin } // Create the Dockerfile and build the base image. - err := createAndBuildBaseImage(ctx, stdout, stderr) - if err != nil { + if err := createAndBuildBaseImage(ctx, stdout, stderr); err != nil { return err } @@ -145,32 +143,27 @@ func createAndBuildIntegrationImage(ctx context.Context, containerRegistry strin // Create integration image if integration files were provided. // Copy dependencies to a dependencies folder under a local directory. - err = updateIntegrationDependencies(dependencies) - if err != nil { + if err := updateIntegrationDependencies(dependencies); err != nil { return err } // Copy routes to a routes folder under a local directory. - err = updateIntegrationRoutes(routes) - if err != nil { + if err := updateIntegrationRoutes(routes); err != nil { return err } // Copy quarkus files in maven subdirectory - err = updateQuarkusDirectory() - if err != nil { + if err := updateQuarkusDirectory(); err != nil { return err } // Copy app files in maven subdirectory - err = updateAppDirectory() - if err != nil { + if err := updateAppDirectory(); err != nil { return err } // Copy lib files in maven subdirectory - err = updateLibDirectory() - if err != nil { + if err := updateLibDirectory(); err != nil { return err } @@ -182,8 +175,7 @@ func createAndBuildIntegrationImage(ctx context.Context, containerRegistry strin } // Create the integration image Docker file. - err = docker.CreateIntegrationImageDockerFile(containerCmd, startsFromLocalFolder) - if err != nil { + if err := docker.CreateIntegrationImageDockerFile(containerCmd, startsFromLocalFolder); err != nil { return err } diff --git a/pkg/util/util.go b/pkg/util/util.go index c68f277179..45e02c0b9d 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -368,20 +368,21 @@ func DirectoryEmpty(directory string) (bool, error) { return ok, err } +// CreateDirectory creates a directory if it does not exist. func CreateDirectory(directory string) error { - if directory != "" { - // If directory does not exist, create it - directoryExists, err := DirectoryExists(directory) - if err != nil { - return err - } + if directory == "" { + return errors.New("directory name must not be empty") + } - if !directoryExists { - // #nosec G301 - err := os.MkdirAll(directory, 0o755) - if err != nil { - return err - } + directoryExists, err := DirectoryExists(directory) + if err != nil { + return err + } + + if !directoryExists { + // #nosec G301 + if err := os.MkdirAll(directory, 0o755); err != nil { + return err } } @@ -682,122 +683,6 @@ func EvaluateCLIAndLazyEnvVars() ([]string, error) { return evaluatedEnvVars, nil } -func CopyIntegrationFilesToDirectory(files []string, directory string) ([]string, error) { - // Create directory if one does not already exist - err := CreateDirectory(directory) - if err != nil { - return nil, err - } - - // Copy files to new location. Also create the list with relocated files. - relocatedFilesList := []string{} - for _, filePath := range files { - newFilePath := path.Join(directory, path.Base(filePath)) - _, err := CopyFile(filePath, newFilePath) - if err != nil { - return relocatedFilesList, err - } - relocatedFilesList = append(relocatedFilesList, newFilePath) - } - - return relocatedFilesList, nil -} - -func CopyQuarkusAppFiles(localDependenciesDirectory string, localQuarkusDir string) error { - // Create directory if one does not already exist - err := CreateDirectory(localQuarkusDir) - if err != nil { - return err - } - - // Transfer all files with a .dat extension and all files with a *-bytecode.jar suffix. - files, err := getRegularFileNamesInDir(localDependenciesDirectory) - if err != nil { - return err - } - for _, file := range files { - if strings.HasSuffix(file, ".dat") || strings.HasSuffix(file, "-bytecode.jar") { - source := path.Join(localDependenciesDirectory, file) - destination := path.Join(localQuarkusDir, file) - _, err = CopyFile(source, destination) - if err != nil { - return err - } - } - } - - return nil -} - -func getRegularFileNamesInDir(directory string) ([]string, error) { - var dirFiles []string - files, err := ioutil.ReadDir(directory) - for _, file := range files { - fileName := file.Name() - - // Do not include hidden files or sub-directories. - if !file.IsDir() && !strings.HasPrefix(fileName, ".") { - dirFiles = append(dirFiles, fileName) - } - } - - if err != nil { - return nil, err - } - - return dirFiles, nil -} - -func CopyLibFiles(localDependenciesDirectory string, localLibDirectory string) error { - // Create directory if one does not already exist - err := CreateDirectory(localLibDirectory) - if err != nil { - return err - } - - fileNames, err := getRegularFileNamesInDir(localDependenciesDirectory) - if err != nil { - return err - } - - for _, dependencyJar := range fileNames { - source := path.Join(localDependenciesDirectory, dependencyJar) - destination := path.Join(localLibDirectory, dependencyJar) - _, err = CopyFile(source, destination) - if err != nil { - return err - } - } - - return nil -} - -func CopyAppFile(localDependenciesDirectory string, localAppDirectory string) error { - // Create directory if one does not already exist - err := CreateDirectory(localAppDirectory) - if err != nil { - return err - } - - fileNames, err := getRegularFileNamesInDir(localDependenciesDirectory) - if err != nil { - return err - } - - for _, dependencyJar := range fileNames { - if strings.HasPrefix(dependencyJar, "camel-k-integration-") { - source := path.Join(localDependenciesDirectory, dependencyJar) - destination := path.Join(localAppDirectory, dependencyJar) - _, err = CopyFile(source, destination) - if err != nil { - return err - } - } - } - - return nil -} - // Open a safe wrapper of os.Open. func Open(name string) (*os.File, error) { return os.Open(filepath.Clean(name)) From 94e464e03dc1b0b6723b6a0a76e557724928446b Mon Sep 17 00:00:00 2001 From: Tadayoshi Sato Date: Thu, 28 Jul 2022 18:43:06 +0900 Subject: [PATCH 3/9] chore(cli): further refactor kamel local cmds --- pkg/cmd/local_build.go | 9 +- pkg/cmd/local_inspect.go | 2 +- pkg/cmd/local_run.go | 12 +- pkg/cmd/local_util.go | 167 ++++++---------------- pkg/cmd/local_util_container.go | 10 +- pkg/cmd/local_util_dirs.go | 244 ++++++++++++++++++++++++++++++++ pkg/util/docker/docker.go | 32 ++--- pkg/util/util.go | 156 -------------------- 8 files changed, 316 insertions(+), 316 deletions(-) create mode 100644 pkg/cmd/local_util_dirs.go diff --git a/pkg/cmd/local_build.go b/pkg/cmd/local_build.go index 079bf0dc38..181f58979f 100644 --- a/pkg/cmd/local_build.go +++ b/pkg/cmd/local_build.go @@ -160,7 +160,7 @@ func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { var dependenciesList, propertyFilesList []string routeFiles := args if !o.BaseImage { - dependencies, err := GetDependencies(o.Context, args, o.Dependencies, o.MavenRepositories, true) + dependencies, err := getDependencies(o.Context, args, o.Dependencies, o.MavenRepositories, true) if err != nil { return err } @@ -176,12 +176,13 @@ func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { dependenciesList = dependencies propertyFilesList = propertyFiles + if o.IntegrationDirectory != "" { // Create dependencies subdirectory. localDependenciesDirectory := getCustomDependenciesDir(o.IntegrationDirectory) // Copy dependencies in persistent IntegrationDirectory/dependencies - dependenciesList, err = CopyIntegrationFilesToDirectory(dependencies, localDependenciesDirectory) + dependenciesList, err = copyIntegrationFilesToDirectory(dependencies, localDependenciesDirectory) if err != nil { return err } @@ -195,7 +196,7 @@ func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { localPropertiesDirectory := getCustomPropertiesDir(o.IntegrationDirectory) // Copy dependencies in persistent IntegrationDirectory/dependencies - propertyFilesList, err = CopyIntegrationFilesToDirectory(propertyFiles, localPropertiesDirectory) + propertyFilesList, err = copyIntegrationFilesToDirectory(propertyFiles, localPropertiesDirectory) if err != nil { return err } @@ -204,7 +205,7 @@ func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { localRoutesDirectory := getCustomRoutesDir(o.IntegrationDirectory) // Copy routes in persistent IntegrationDirectory/dependencies - routeFiles, err = CopyIntegrationFilesToDirectory(args, localRoutesDirectory) + routeFiles, err = copyIntegrationFilesToDirectory(args, localRoutesDirectory) if err != nil { return err } diff --git a/pkg/cmd/local_inspect.go b/pkg/cmd/local_inspect.go index f5e523bc17..1c180d56bd 100644 --- a/pkg/cmd/local_inspect.go +++ b/pkg/cmd/local_inspect.go @@ -87,7 +87,7 @@ func (o *localInspectCmdOptions) init() error { } func (o *localInspectCmdOptions) run(cmd *cobra.Command, args []string) error { - dependencies, err := GetDependencies(o.Context, args, o.Dependencies, o.MavenRepositories, o.AllDependencies) + dependencies, err := getDependencies(o.Context, args, o.Dependencies, o.MavenRepositories, o.AllDependencies) if err != nil { return err } diff --git a/pkg/cmd/local_run.go b/pkg/cmd/local_run.go index ad6f77ce3a..951e455f3c 100644 --- a/pkg/cmd/local_run.go +++ b/pkg/cmd/local_run.go @@ -25,8 +25,6 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" - - "github.com/apache/camel-k/pkg/util" ) func newCmdLocalRun(localCmdOptions *LocalCmdOptions) (*cobra.Command, *localRunCmdOptions) { @@ -171,7 +169,7 @@ func (o *localRunCmdOptions) run(cmd *cobra.Command, args []string) error { // /../quarkus/quarkus-application.dat // /../quarkus/generated-bytecode.jar localQuarkusDir := getCustomQuarkusDir(o.IntegrationDirectory) - err = CopyQuarkusAppFiles(localDependenciesDirectory, localQuarkusDir) + err = copyQuarkusAppFiles(localDependenciesDirectory, localQuarkusDir) if err != nil { return err } @@ -179,7 +177,7 @@ func (o *localRunCmdOptions) run(cmd *cobra.Command, args []string) error { // The dependency jar files need to be at a specific location i.e.: // /../lib/main/*.jar localLibDirectory := getCustomLibDir(o.IntegrationDirectory) - err = CopyLibFiles(localDependenciesDirectory, localLibDirectory) + err = copyLibFiles(localDependenciesDirectory, localLibDirectory) if err != nil { return err } @@ -187,12 +185,12 @@ func (o *localRunCmdOptions) run(cmd *cobra.Command, args []string) error { // The Camel K jar file needs to be at a specific location i.e.: // /../app/camel-k-integration-X.X.X{-SNAPSHOT}.jar localAppDirectory := getCustomAppDir(o.IntegrationDirectory) - err = CopyAppFile(localDependenciesDirectory, localAppDirectory) + err = copyAppFile(localDependenciesDirectory, localAppDirectory) if err != nil { return err } } else { - computedDependencies, err := GetDependencies(o.Context, args, o.Dependencies, o.MavenRepositories, true) + computedDependencies, err := getDependencies(o.Context, args, o.Dependencies, o.MavenRepositories, true) if err != nil { return err } @@ -238,7 +236,7 @@ func (o *localRunCmdOptions) run(cmd *cobra.Command, args []string) error { return err } } else { - propertiesDir := util.GetLocalPropertiesDir() + propertiesDir := getLocalPropertiesDir() if hasIntegrationDir { propertiesDir = getCustomPropertiesDir(o.IntegrationDirectory) } diff --git a/pkg/cmd/local_util.go b/pkg/cmd/local_util.go index 3ecd9adc79..67ea7f9051 100644 --- a/pkg/cmd/local_util.go +++ b/pkg/cmd/local_util.go @@ -44,8 +44,8 @@ var acceptedDependencyTypes = []string{ "github", "gitlab", "bitbucket", "gitee", "azure", } -// GetDependencies resolves and gets the list of dependencies from catalog and sources. -func GetDependencies(ctx context.Context, args []string, additionalDependencies []string, repositories []string, allDependencies bool) ([]string, error) { +// getDependencies resolves and gets the list of dependencies from catalog and sources. +func getDependencies(ctx context.Context, args []string, additionalDependencies []string, repositories []string, allDependencies bool) ([]string, error) { // Fetch existing catalog or create new one if one does not already exist catalog, err := createCamelCatalog(ctx) if err != nil { @@ -114,7 +114,7 @@ func getTransitiveDependencies(ctx context.Context, catalog *camel.RuntimeCatalo return nil, err } - mc := maven.NewContext(util.MavenWorkingDirectory) + mc := maven.NewContext(MavenWorkingDirectory) mc.LocalRepository = "" if len(repositories) > 0 { @@ -150,27 +150,31 @@ func getTransitiveDependencies(ctx context.Context, catalog *camel.RuntimeCatalo return transitiveDependencies, nil } -func getRegularFilesInDir(directory string) ([]string, error) { +func getRegularFilesInDir(directory string, dirnameInPath bool) ([]string, error) { var dirFiles []string files, err := ioutil.ReadDir(directory) + if err != nil { + return nil, err + } + for _, file := range files { fileName := file.Name() // Do not include hidden files or sub-directories. if !file.IsDir() && !strings.HasPrefix(fileName, ".") { - dirFiles = append(dirFiles, path.Join(directory, fileName)) + if dirnameInPath { + dirFiles = append(dirFiles, path.Join(directory, fileName)) + } else { + dirFiles = append(dirFiles, fileName) + } } } - if err != nil { - return nil, err - } - return dirFiles, nil } func getLocalBuildDependencies(integrationDirectory string) ([]string, error) { - locallyBuiltDependencies, err := getRegularFilesInDir(getCustomDependenciesDir(integrationDirectory)) + locallyBuiltDependencies, err := getRegularFilesInDir(getCustomDependenciesDir(integrationDirectory), true) if err != nil { return nil, err } @@ -178,7 +182,7 @@ func getLocalBuildDependencies(integrationDirectory string) ([]string, error) { } func getLocalBuildProperties(integrationDirectory string) ([]string, error) { - locallyBuiltProperties, err := getRegularFilesInDir(getCustomPropertiesDir(integrationDirectory)) + locallyBuiltProperties, err := getRegularFilesInDir(getCustomPropertiesDir(integrationDirectory), true) if err != nil { return nil, err } @@ -186,7 +190,7 @@ func getLocalBuildProperties(integrationDirectory string) ([]string, error) { } func getLocalBuildRoutes(integrationDirectory string) ([]string, error) { - locallyBuiltRoutes, err := getRegularFilesInDir(getCustomRoutesDir(integrationDirectory)) + locallyBuiltRoutes, err := getRegularFilesInDir(getCustomRoutesDir(integrationDirectory), true) if err != nil { return nil, err } @@ -347,17 +351,15 @@ func validatePropertyFile(fileName string) error { func updateIntegrationProperties(properties []string, propertyFiles []string, hasIntegrationDir bool) ([]string, error) { // Create properties directory under Maven working directory. // This ensures that property files of different integrations do not clash. - err := util.CreateLocalPropertiesDirectory() - if err != nil { + if err := createLocalPropertiesDirectory(); err != nil { return nil, err } // Relocate properties files to this integration's property directory. relocatedPropertyFiles := []string{} for _, propertyFile := range propertyFiles { - relocatedPropertyFile := path.Join(util.GetLocalPropertiesDir(), path.Base(propertyFile)) - _, err = util.CopyFile(propertyFile, relocatedPropertyFile) - if err != nil { + relocatedPropertyFile := path.Join(getLocalPropertiesDir(), path.Base(propertyFile)) + if _, err := util.CopyFile(propertyFile, relocatedPropertyFile); err != nil { return nil, err } relocatedPropertyFiles = append(relocatedPropertyFiles, relocatedPropertyFile) @@ -366,9 +368,8 @@ func updateIntegrationProperties(properties []string, propertyFiles []string, ha if !hasIntegrationDir { // Output list of properties to property file if any CLI properties were given. if len(properties) > 0 { - propertyFilePath := path.Join(util.GetLocalPropertiesDir(), "CLI.properties") - err = ioutil.WriteFile(propertyFilePath, []byte(strings.Join(properties, "\n")), 0o600) - if err != nil { + propertyFilePath := path.Join(getLocalPropertiesDir(), "CLI.properties") + if err := ioutil.WriteFile(propertyFilePath, []byte(strings.Join(properties, "\n")), 0o600); err != nil { return nil, err } relocatedPropertyFiles = append(relocatedPropertyFiles, propertyFilePath) @@ -381,7 +382,7 @@ func updateIntegrationProperties(properties []string, propertyFiles []string, ha func updateIntegrationDependencies(dependencies []string) error { // Create dependencies directory under Maven working directory. // This ensures that dependencies will be removed after they are not needed. - err := util.CreateLocalDependenciesDirectory() + err := createLocalDependenciesDirectory() if err != nil { return err } @@ -391,9 +392,9 @@ func updateIntegrationDependencies(dependencies []string) error { var targetPath string basePath := util.SubstringFrom(dependency, util.QuarkusDependenciesBaseDirectory) if basePath != "" { - targetPath = path.Join(util.GetLocalDependenciesDir(), basePath) + targetPath = path.Join(getLocalDependenciesDir(), basePath) } else { - targetPath = path.Join(util.GetLocalDependenciesDir(), path.Base(dependency)) + targetPath = path.Join(getLocalDependenciesDir(), path.Base(dependency)) } _, err = util.CopyFile(dependency, targetPath) if err != nil { @@ -405,13 +406,13 @@ func updateIntegrationDependencies(dependencies []string) error { } func updateIntegrationRoutes(routes []string) error { - err := util.CreateLocalRoutesDirectory() + err := createLocalRoutesDirectory() if err != nil { return err } for _, route := range routes { - _, err = util.CopyFile(route, path.Join(util.GetLocalRoutesDir(), path.Base(route))) + _, err = util.CopyFile(route, path.Join(getLocalRoutesDir(), path.Base(route))) if err != nil { return err } @@ -421,104 +422,42 @@ func updateIntegrationRoutes(routes []string) error { } func updateQuarkusDirectory() error { - err := util.CreateLocalQuarkusDirectory() + err := createLocalQuarkusDirectory() if err != nil { return err } // ignore error if custom dir doesn't exist - _ = CopyQuarkusAppFiles(util.CustomQuarkusDirectoryName, util.GetLocalQuarkusDir()) + _ = copyQuarkusAppFiles(util.CustomQuarkusDirectoryName, getLocalQuarkusDir()) return nil } func updateAppDirectory() error { - err := util.CreateLocalAppDirectory() + err := createLocalAppDirectory() if err != nil { return err } // ignore error if custom dir doesn't exist - _ = CopyAppFile(util.CustomAppDirectoryName, util.GetLocalAppDir()) + _ = copyAppFile(util.CustomAppDirectoryName, getLocalAppDir()) return nil } func updateLibDirectory() error { - err := util.CreateLocalLibDirectory() + err := createLocalLibDirectory() if err != nil { return err } // ignore error if custom dir doesn't exist - _ = CopyLibFiles(util.CustomLibDirectoryName, util.GetLocalLibDir()) - - return nil -} - -func createMavenWorkingDirectory() error { - // Create local Maven context - temporaryDirectory, err := ioutil.TempDir(os.TempDir(), "maven-") - if err != nil { - return err - } - - // Set the Maven directory to the default value - util.MavenWorkingDirectory = temporaryDirectory - - return nil -} - -func deleteMavenWorkingDirectory() error { - // Remove directory used for computing the dependencies - return os.RemoveAll(util.MavenWorkingDirectory) -} - -func getCustomDependenciesDir(integrationDirectory string) string { - return path.Join(integrationDirectory, "dependencies") -} - -func getCustomPropertiesDir(integrationDirectory string) string { - return path.Join(integrationDirectory, "properties") -} - -func getCustomRoutesDir(integrationDirectory string) string { - return path.Join(integrationDirectory, "routes") -} - -func getCustomQuarkusDir(integrationDirectory string) string { - parentDir := path.Dir(strings.TrimSuffix(integrationDirectory, "/")) - return path.Join(parentDir, "quarkus") -} - -func getCustomLibDir(integrationDirectory string) string { - parentDir := path.Dir(strings.TrimSuffix(integrationDirectory, "/")) - return path.Join(parentDir, "lib/main") -} - -func getCustomAppDir(integrationDirectory string) string { - parentDir := path.Dir(strings.TrimSuffix(integrationDirectory, "/")) - return path.Join(parentDir, "app") -} - -func deleteLocalIntegrationDirs(integrationDirectory string) error { - dirs := []string{ - getCustomQuarkusDir(integrationDirectory), - getCustomLibDir(integrationDirectory), - getCustomAppDir(integrationDirectory), - } - - for _, dir := range dirs { - err := os.RemoveAll(dir) - if err != nil { - return err - } - } + _ = copyLibFiles(util.CustomLibDirectoryName, getLocalLibDir()) return nil } -func CopyIntegrationFilesToDirectory(files []string, directory string) ([]string, error) { +func copyIntegrationFilesToDirectory(files []string, directory string) ([]string, error) { // Create directory if one does not already exist if err := util.CreateDirectory(directory); err != nil { return nil, err @@ -538,15 +477,14 @@ func CopyIntegrationFilesToDirectory(files []string, directory string) ([]string return relocatedFilesList, nil } -func CopyQuarkusAppFiles(localDependenciesDirectory string, localQuarkusDir string) error { +func copyQuarkusAppFiles(localDependenciesDirectory string, localQuarkusDir string) error { // Create directory if one does not already exist - err := util.CreateDirectory(localQuarkusDir) - if err != nil { + if err := util.CreateDirectory(localQuarkusDir); err != nil { return err } // Transfer all files with a .dat extension and all files with a *-bytecode.jar suffix. - files, err := getRegularFileNamesInDir(localDependenciesDirectory) + files, err := getRegularFilesInDir(localDependenciesDirectory, false) if err != nil { return err } @@ -564,14 +502,13 @@ func CopyQuarkusAppFiles(localDependenciesDirectory string, localQuarkusDir stri return nil } -func CopyLibFiles(localDependenciesDirectory string, localLibDirectory string) error { +func copyLibFiles(localDependenciesDirectory string, localLibDirectory string) error { // Create directory if one does not already exist - err := util.CreateDirectory(localLibDirectory) - if err != nil { + if err := util.CreateDirectory(localLibDirectory); err != nil { return err } - fileNames, err := getRegularFileNamesInDir(localDependenciesDirectory) + fileNames, err := getRegularFilesInDir(localDependenciesDirectory, false) if err != nil { return err } @@ -588,14 +525,13 @@ func CopyLibFiles(localDependenciesDirectory string, localLibDirectory string) e return nil } -func CopyAppFile(localDependenciesDirectory string, localAppDirectory string) error { +func copyAppFile(localDependenciesDirectory string, localAppDirectory string) error { // Create directory if one does not already exist - err := util.CreateDirectory(localAppDirectory) - if err != nil { + if err := util.CreateDirectory(localAppDirectory); err != nil { return err } - fileNames, err := getRegularFileNamesInDir(localDependenciesDirectory) + fileNames, err := getRegularFilesInDir(localDependenciesDirectory, false) if err != nil { return err } @@ -613,22 +549,3 @@ func CopyAppFile(localDependenciesDirectory string, localAppDirectory string) er return nil } - -func getRegularFileNamesInDir(directory string) ([]string, error) { - var dirFiles []string - files, err := ioutil.ReadDir(directory) - for _, file := range files { - fileName := file.Name() - - // Do not include hidden files or sub-directories. - if !file.IsDir() && !strings.HasPrefix(fileName, ".") { - dirFiles = append(dirFiles, fileName) - } - } - - if err != nil { - return nil, err - } - - return dirFiles, nil -} diff --git a/pkg/cmd/local_util_container.go b/pkg/cmd/local_util_container.go index 64e9dd886b..e03824b7cc 100644 --- a/pkg/cmd/local_util_container.go +++ b/pkg/cmd/local_util_container.go @@ -35,8 +35,8 @@ import ( // Local Docker file system management functions. +// createDockerBaseWorkingDirectory creates local docker base directory. func createDockerBaseWorkingDirectory() error { - // Create local docker base directory. temporaryDirectory, err := ioutil.TempDir(os.TempDir(), "docker-base-") if err != nil { return err @@ -48,13 +48,13 @@ func createDockerBaseWorkingDirectory() error { return nil } +// deleteDockerBaseWorkingDirectory removes directory used for computing the base dependencies. func deleteDockerBaseWorkingDirectory() error { - // Remove directory used for computing the dependencies. return os.RemoveAll(docker.BaseWorkingDirectory) } +// createDockerWorkingDirectory creates local docker directory. func createDockerWorkingDirectory() error { - // Create local docker base directory. temporaryDirectory, err := ioutil.TempDir(os.TempDir(), "docker-") if err != nil { return err @@ -66,8 +66,8 @@ func createDockerWorkingDirectory() error { return nil } +// deleteDockerWorkingDirectory removes directory used for computing the integration dependencies. func deleteDockerWorkingDirectory() error { - // Remove directory used for computing the dependencies. return os.RemoveAll(docker.IntegrationWorkingDirectory) } @@ -180,7 +180,7 @@ func createAndBuildIntegrationImage(ctx context.Context, containerRegistry strin } // Get the Docker command arguments for building the base image and create the command. - args := docker.BuildIntegrationImageArgs(image) + args := docker.BuildIntegrationImageArgs(image, MavenWorkingDirectory) cmd := exec.CommandContext(ctx, "docker", args...) // Set stdout and stderr. diff --git a/pkg/cmd/local_util_dirs.go b/pkg/cmd/local_util_dirs.go new file mode 100644 index 0000000000..7d0311d121 --- /dev/null +++ b/pkg/cmd/local_util_dirs.go @@ -0,0 +1,244 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cmd + +import ( + "io/ioutil" + "os" + "path" + "strings" + + "github.com/apache/camel-k/pkg/util" +) + +// MavenWorkingDirectory is the directory used by Maven for an invocation of the kamel local command. +// By default, a temporary folder will be used. +var MavenWorkingDirectory = "" + +// createMavenWorkingDirectory creates local Maven working directory. +func createMavenWorkingDirectory() error { + temporaryDirectory, err := ioutil.TempDir(os.TempDir(), "maven-") + if err != nil { + return err + } + + // Set the Maven directory to the default value + MavenWorkingDirectory = temporaryDirectory + + return nil +} + +// deleteMavenWorkingDirectory removes local Maven working directory. +func deleteMavenWorkingDirectory() error { + return os.RemoveAll(MavenWorkingDirectory) +} + +// getLocalDependenciesDir returns /dependencies. +func getLocalDependenciesDir() string { + return path.Join(MavenWorkingDirectory, util.DefaultDependenciesDirectoryName) +} + +func createLocalDependenciesDirectory() error { + // Do not create a directory unless the maven directory contains a valid value. + if MavenWorkingDirectory == "" { + return nil + } + + directoryExists, err := util.DirectoryExists(getLocalDependenciesDir()) + if err != nil { + return err + } + + if !directoryExists { + if err := os.MkdirAll(getLocalDependenciesDir(), 0o700); err != nil { + return err + } + } + + return nil +} + +// getLocalPropertiesDir returns /properties. +func getLocalPropertiesDir() string { + return path.Join(MavenWorkingDirectory, util.DefaultPropertiesDirectoryName) +} + +func createLocalPropertiesDirectory() error { + // Do not create a directory unless the maven directory contains a valid value. + if MavenWorkingDirectory == "" { + return nil + } + + directoryExists, err := util.DirectoryExists(getLocalPropertiesDir()) + if err != nil { + return err + } + + if !directoryExists { + err := os.MkdirAll(getLocalPropertiesDir(), 0o700) + if err != nil { + return err + } + } + + return nil +} + +// getLocalRoutesDir returns /routes. +func getLocalRoutesDir() string { + return path.Join(MavenWorkingDirectory, util.DefaultRoutesDirectoryName) +} + +func createLocalRoutesDirectory() error { + // Do not create a directory unless the maven directory contains a valid value. + if MavenWorkingDirectory == "" { + return nil + } + + directoryExists, err := util.DirectoryExists(getLocalRoutesDir()) + if err != nil { + return err + } + + if !directoryExists { + if err := os.MkdirAll(getLocalRoutesDir(), 0o700); err != nil { + return err + } + } + + return nil +} + +// getLocalQuarkusDir returns /quarkus. +func getLocalQuarkusDir() string { + return path.Join(MavenWorkingDirectory, util.CustomQuarkusDirectoryName) +} + +func createLocalQuarkusDirectory() error { + // Do not create a directory unless the maven directory contains a valid value. + if MavenWorkingDirectory == "" { + return nil + } + + directoryExists, err := util.DirectoryExists(getLocalQuarkusDir()) + if err != nil { + return err + } + + if !directoryExists { + if err := os.MkdirAll(getLocalQuarkusDir(), 0o700); err != nil { + return err + } + } + + return nil +} + +// getLocalAppDir returns /app. +func getLocalAppDir() string { + return path.Join(MavenWorkingDirectory, util.CustomAppDirectoryName) +} + +func createLocalAppDirectory() error { + // Do not create a directory unless the maven directory contains a valid value. + if MavenWorkingDirectory == "" { + return nil + } + + directoryExists, err := util.DirectoryExists(getLocalAppDir()) + if err != nil { + return err + } + + if !directoryExists { + if err := os.MkdirAll(getLocalAppDir(), 0o700); err != nil { + return err + } + } + + return nil +} + +// getLocalLibDir returns /lib/main. +func getLocalLibDir() string { + return path.Join(MavenWorkingDirectory, util.CustomLibDirectoryName) +} + +func createLocalLibDirectory() error { + // Do not create a directory unless the maven directory contains a valid value. + if MavenWorkingDirectory == "" { + return nil + } + + directoryExists, err := util.DirectoryExists(getLocalLibDir()) + if err != nil { + return err + } + + if !directoryExists { + if err := os.MkdirAll(getLocalLibDir(), 0o700); err != nil { + return err + } + } + + return nil +} + +func getCustomDependenciesDir(dir string) string { + return path.Join(dir, util.DefaultDependenciesDirectoryName) +} + +func getCustomPropertiesDir(dir string) string { + return path.Join(dir, util.DefaultPropertiesDirectoryName) +} + +func getCustomRoutesDir(dir string) string { + return path.Join(dir, util.DefaultRoutesDirectoryName) +} + +func getCustomQuarkusDir(dir string) string { + parentDir := path.Dir(strings.TrimSuffix(dir, "/")) + return path.Join(parentDir, util.CustomQuarkusDirectoryName) +} + +func getCustomLibDir(dir string) string { + parentDir := path.Dir(strings.TrimSuffix(dir, "/")) + return path.Join(parentDir, util.CustomLibDirectoryName) +} + +func getCustomAppDir(dir string) string { + parentDir := path.Dir(strings.TrimSuffix(dir, "/")) + return path.Join(parentDir, "app") +} + +func deleteLocalIntegrationDirs(dir string) error { + dirs := []string{ + getCustomQuarkusDir(dir), + getCustomLibDir(dir), + getCustomAppDir(dir), + } + + for _, dir := range dirs { + err := os.RemoveAll(dir) + if err != nil { + return err + } + } + + return nil +} diff --git a/pkg/util/docker/docker.go b/pkg/util/docker/docker.go index 38bf8a0e9e..a053434c9d 100644 --- a/pkg/util/docker/docker.go +++ b/pkg/util/docker/docker.go @@ -92,31 +92,27 @@ func CreateIntegrationImageDockerFile(integrationRunCmd *exec.Cmd, startsFromLoc return nil } -// BuildBaseImageArgs --. +// BuildBaseImageArgs constructs the docker command: +// +// docker build -f /Dockerfile -t / . +// func BuildBaseImageArgs() []string { - // Construct the docker command: - // - // docker build -f /Dockerfile -t / - // - // Add register return BuildImageArgs(BaseWorkingDirectory, GetBaseImagePath(), BaseWorkingDirectory) } -// BuildIntegrationImageArgs --. -func BuildIntegrationImageArgs(imagePath string) []string { - // Construct the docker command: - // - // docker build -f /Dockerfile -t - // - return BuildImageArgs(IntegrationWorkingDirectory, imagePath, util.MavenWorkingDirectory) +// BuildIntegrationImageArgs constructs the docker command: +// +// docker build -f /Dockerfile -t . +// +func BuildIntegrationImageArgs(imagePath string, mavenWorkingDirectory string) []string { + return BuildImageArgs(IntegrationWorkingDirectory, imagePath, mavenWorkingDirectory) } -// RunIntegrationImageArgs --. +// RunIntegrationImageArgs constructs the docker command: +// +// docker run --network= --env LAZY_ENV_VAR=value /. +// func RunIntegrationImageArgs(imagePath string) ([]string, error) { - // Construct the docker command: - // - // docker run --network= --env LAZY_ENV_VAR=value / - // return RunImageArgs(imagePath, latestTag) } diff --git a/pkg/util/util.go b/pkg/util/util.go index 45e02c0b9d..878c5913d2 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -44,10 +44,6 @@ import ( // Directories and file names: -// MavenWorkingDirectory is the directory used by Maven for an invocation of the kamel local command. -// By default, a temporary folder will be used. -var MavenWorkingDirectory = "" - // DefaultDependenciesDirectoryName --. const DefaultDependenciesDirectoryName = "dependencies" @@ -479,158 +475,6 @@ func WriteToFile(filePath string, fileContents string) error { return nil } -// Local directories: - -// GetLocalPropertiesDir -- /properties. -func GetLocalPropertiesDir() string { - return path.Join(MavenWorkingDirectory, DefaultPropertiesDirectoryName) -} - -// GetLocalDependenciesDir --/dependencies. -func GetLocalDependenciesDir() string { - return path.Join(MavenWorkingDirectory, DefaultDependenciesDirectoryName) -} - -// GetLocalRoutesDir -- /routes. -func GetLocalRoutesDir() string { - return path.Join(MavenWorkingDirectory, DefaultRoutesDirectoryName) -} - -// GetLocalQuarkusDir -- /quarkus. -func GetLocalQuarkusDir() string { - return path.Join(MavenWorkingDirectory, CustomQuarkusDirectoryName) -} - -// GetLocalAppDir -- /app. -func GetLocalAppDir() string { - return path.Join(MavenWorkingDirectory, CustomAppDirectoryName) -} - -// GetLocalLibDir -- /lib/main. -func GetLocalLibDir() string { - return path.Join(MavenWorkingDirectory, CustomLibDirectoryName) -} - -func CreateLocalPropertiesDirectory() error { - // Do not create a directory unless the maven directory contains a valid value. - if MavenWorkingDirectory == "" { - return nil - } - - directoryExists, err := DirectoryExists(GetLocalPropertiesDir()) - if err != nil { - return err - } - - if !directoryExists { - err := os.MkdirAll(GetLocalPropertiesDir(), 0o700) - if err != nil { - return err - } - } - return nil -} - -func CreateLocalDependenciesDirectory() error { - // Do not create a directory unless the maven directory contains a valid value. - if MavenWorkingDirectory == "" { - return nil - } - - directoryExists, err := DirectoryExists(GetLocalDependenciesDir()) - if err != nil { - return err - } - - if !directoryExists { - err := os.MkdirAll(GetLocalDependenciesDir(), 0o700) - if err != nil { - return err - } - } - return nil -} - -func CreateLocalRoutesDirectory() error { - // Do not create a directory unless the maven directory contains a valid value. - if MavenWorkingDirectory == "" { - return nil - } - - directoryExists, err := DirectoryExists(GetLocalRoutesDir()) - if err != nil { - return err - } - - if !directoryExists { - err := os.MkdirAll(GetLocalRoutesDir(), 0o700) - if err != nil { - return err - } - } - return nil -} - -func CreateLocalQuarkusDirectory() error { - // Do not create a directory unless the maven directory contains a valid value. - if MavenWorkingDirectory == "" { - return nil - } - - directoryExists, err := DirectoryExists(GetLocalQuarkusDir()) - if err != nil { - return err - } - - if !directoryExists { - err := os.MkdirAll(GetLocalQuarkusDir(), 0o700) - if err != nil { - return err - } - } - return nil -} - -func CreateLocalAppDirectory() error { - // Do not create a directory unless the maven directory contains a valid value. - if MavenWorkingDirectory == "" { - return nil - } - - directoryExists, err := DirectoryExists(GetLocalAppDir()) - if err != nil { - return err - } - - if !directoryExists { - err := os.MkdirAll(GetLocalAppDir(), 0o700) - if err != nil { - return err - } - } - return nil -} - -func CreateLocalLibDirectory() error { - // Do not create a directory unless the maven directory contains a valid value. - if MavenWorkingDirectory == "" { - return nil - } - - directoryExists, err := DirectoryExists(GetLocalLibDir()) - if err != nil { - return err - } - - if !directoryExists { - err := os.MkdirAll(GetLocalLibDir(), 0o700) - if err != nil { - return err - } - } - return nil -} - func GetEnvironmentVariable(variable string) (string, error) { value, isPresent := os.LookupEnv(variable) if !isPresent { From 96121358b8bebe7ca8efeca55fb19c4a02335b21 Mon Sep 17 00:00:00 2001 From: Tadayoshi Sato Date: Thu, 28 Jul 2022 22:46:16 +0900 Subject: [PATCH 4/9] chore(cli): further refactor kamel local cmds --- pkg/cmd/local_build.go | 51 +++++++++++++-------------------- pkg/cmd/local_run.go | 6 ++-- pkg/cmd/local_util.go | 44 ++++++++++++---------------- pkg/cmd/local_util_container.go | 34 ++++++++++++++++------ pkg/util/docker/docker.go | 3 +- pkg/util/docker/docker_base.go | 4 +-- 6 files changed, 69 insertions(+), 73 deletions(-) diff --git a/pkg/cmd/local_build.go b/pkg/cmd/local_build.go index 181f58979f..bc506c27b4 100644 --- a/pkg/cmd/local_build.go +++ b/pkg/cmd/local_build.go @@ -159,6 +159,7 @@ func (o *localBuildCmdOptions) init(args []string) error { func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { var dependenciesList, propertyFilesList []string routeFiles := args + if !o.BaseImage { dependencies, err := getDependencies(o.Context, args, o.Dependencies, o.MavenRepositories, true) if err != nil { @@ -177,56 +178,44 @@ func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { dependenciesList = dependencies propertyFilesList = propertyFiles + // Integration directory can only be used when building an integration image or when we just + // build the integration without also building the image. A local build of the integration is + // represented by all the files that define the integration: dependencies, properties, and routes. if o.IntegrationDirectory != "" { - // Create dependencies subdirectory. - localDependenciesDirectory := getCustomDependenciesDir(o.IntegrationDirectory) - - // Copy dependencies in persistent IntegrationDirectory/dependencies - dependenciesList, err = copyIntegrationFilesToDirectory(dependencies, localDependenciesDirectory) + localDependenciesDir := getCustomDependenciesDir(o.IntegrationDirectory) + dependenciesList, err = copyIntegrationFilesToDirectory(dependencies, localDependenciesDir) if err != nil { return err } - // Once dependencies have been copied to local folder, we can exit. if o.DependenciesOnly { + // Once dependencies have been copied to local folder, we can exit. return nil } - // Create dependencies subdirectory. - localPropertiesDirectory := getCustomPropertiesDir(o.IntegrationDirectory) - - // Copy dependencies in persistent IntegrationDirectory/dependencies - propertyFilesList, err = copyIntegrationFilesToDirectory(propertyFiles, localPropertiesDirectory) + localPropertiesDir := getCustomPropertiesDir(o.IntegrationDirectory) + propertyFilesList, err = copyIntegrationFilesToDirectory(propertyFiles, localPropertiesDir) if err != nil { return err } - // Save routes. - localRoutesDirectory := getCustomRoutesDir(o.IntegrationDirectory) - - // Copy routes in persistent IntegrationDirectory/dependencies - routeFiles, err = copyIntegrationFilesToDirectory(args, localRoutesDirectory) + localRoutesDir := getCustomRoutesDir(o.IntegrationDirectory) + routeFiles, err = copyIntegrationFilesToDirectory(args, localRoutesDir) if err != nil { return err } - } - } - - // Integration directory can only be used when building an integration image or when we just - // build the integration without also building the image. A local build of the integration is - // represented by all the files that define the integration: dependencies, properties and routes. - // The only case in which we should not execute the integration image creation is when we want to - // just output the files that comprise the integration locally. - if o.IntegrationDirectory != "" && o.Image == "" { - return nil + // The only case in which we should not execute the integration image creation is when we want to + // just output the files that comprise the integration locally. + if o.Image == "" { + return nil + } + } } - // Create and build integration image. - err := createAndBuildIntegrationImage(o.Context, o.ContainerRegistry, o.BaseImage, - o.Image, propertyFilesList, dependenciesList, routeFiles, false, - cmd.OutOrStdout(), cmd.ErrOrStderr()) - if err != nil { + if err := createAndBuildIntegrationImage(o.Context, o.ContainerRegistry, o.BaseImage, o.Image, + propertyFilesList, dependenciesList, routeFiles, false, + cmd.OutOrStdout(), cmd.ErrOrStderr()); err != nil { return err } diff --git a/pkg/cmd/local_run.go b/pkg/cmd/local_run.go index 951e455f3c..62e53205a1 100644 --- a/pkg/cmd/local_run.go +++ b/pkg/cmd/local_run.go @@ -224,9 +224,9 @@ func (o *localRunCmdOptions) run(cmd *cobra.Command, args []string) error { // If this is a containerized local run, create, build and run the container image. if o.Containerize { - // Create and build integration image. - err := createAndBuildIntegrationImage(o.Context, "", false, o.Image, propertyFiles, dependencies, routes, hasIntegrationDir, cmd.OutOrStdout(), cmd.ErrOrStderr()) - if err != nil { + if err := createAndBuildIntegrationImage(o.Context, "", false, o.Image, + propertyFiles, dependencies, routes, hasIntegrationDir, + cmd.OutOrStdout(), cmd.ErrOrStderr()); err != nil { return err } diff --git a/pkg/cmd/local_util.go b/pkg/cmd/local_util.go index 67ea7f9051..bc0d266194 100644 --- a/pkg/cmd/local_util.go +++ b/pkg/cmd/local_util.go @@ -357,8 +357,9 @@ func updateIntegrationProperties(properties []string, propertyFiles []string, ha // Relocate properties files to this integration's property directory. relocatedPropertyFiles := []string{} + dir := getLocalPropertiesDir() for _, propertyFile := range propertyFiles { - relocatedPropertyFile := path.Join(getLocalPropertiesDir(), path.Base(propertyFile)) + relocatedPropertyFile := path.Join(dir, path.Base(propertyFile)) if _, err := util.CopyFile(propertyFile, relocatedPropertyFile); err != nil { return nil, err } @@ -368,7 +369,7 @@ func updateIntegrationProperties(properties []string, propertyFiles []string, ha if !hasIntegrationDir { // Output list of properties to property file if any CLI properties were given. if len(properties) > 0 { - propertyFilePath := path.Join(getLocalPropertiesDir(), "CLI.properties") + propertyFilePath := path.Join(dir, "CLI.properties") if err := ioutil.WriteFile(propertyFilePath, []byte(strings.Join(properties, "\n")), 0o600); err != nil { return nil, err } @@ -382,22 +383,21 @@ func updateIntegrationProperties(properties []string, propertyFiles []string, ha func updateIntegrationDependencies(dependencies []string) error { // Create dependencies directory under Maven working directory. // This ensures that dependencies will be removed after they are not needed. - err := createLocalDependenciesDirectory() - if err != nil { + if err := createLocalDependenciesDirectory(); err != nil { return err } // Relocate dependencies files to this integration's dependencies directory + dir := getLocalDependenciesDir() for _, dependency := range dependencies { var targetPath string basePath := util.SubstringFrom(dependency, util.QuarkusDependenciesBaseDirectory) if basePath != "" { - targetPath = path.Join(getLocalDependenciesDir(), basePath) + targetPath = path.Join(dir, basePath) } else { - targetPath = path.Join(getLocalDependenciesDir(), path.Base(dependency)) + targetPath = path.Join(dir, path.Base(dependency)) } - _, err = util.CopyFile(dependency, targetPath) - if err != nil { + if _, err := util.CopyFile(dependency, targetPath); err != nil { return err } } @@ -406,14 +406,13 @@ func updateIntegrationDependencies(dependencies []string) error { } func updateIntegrationRoutes(routes []string) error { - err := createLocalRoutesDirectory() - if err != nil { + if err := createLocalRoutesDirectory(); err != nil { return err } + dir := getLocalRoutesDir() for _, route := range routes { - _, err = util.CopyFile(route, path.Join(getLocalRoutesDir(), path.Base(route))) - if err != nil { + if _, err := util.CopyFile(route, path.Join(dir, path.Base(route))); err != nil { return err } } @@ -422,8 +421,7 @@ func updateIntegrationRoutes(routes []string) error { } func updateQuarkusDirectory() error { - err := createLocalQuarkusDirectory() - if err != nil { + if err := createLocalQuarkusDirectory(); err != nil { return err } @@ -434,8 +432,7 @@ func updateQuarkusDirectory() error { } func updateAppDirectory() error { - err := createLocalAppDirectory() - if err != nil { + if err := createLocalAppDirectory(); err != nil { return err } @@ -446,8 +443,7 @@ func updateAppDirectory() error { } func updateLibDirectory() error { - err := createLocalLibDirectory() - if err != nil { + if err := createLocalLibDirectory(); err != nil { return err } @@ -467,8 +463,7 @@ func copyIntegrationFilesToDirectory(files []string, directory string) ([]string relocatedFilesList := []string{} for _, filePath := range files { newFilePath := path.Join(directory, path.Base(filePath)) - _, err := util.CopyFile(filePath, newFilePath) - if err != nil { + if _, err := util.CopyFile(filePath, newFilePath); err != nil { return relocatedFilesList, err } relocatedFilesList = append(relocatedFilesList, newFilePath) @@ -492,8 +487,7 @@ func copyQuarkusAppFiles(localDependenciesDirectory string, localQuarkusDir stri if strings.HasSuffix(file, ".dat") || strings.HasSuffix(file, "-bytecode.jar") { source := path.Join(localDependenciesDirectory, file) destination := path.Join(localQuarkusDir, file) - _, err = util.CopyFile(source, destination) - if err != nil { + if _, err = util.CopyFile(source, destination); err != nil { return err } } @@ -516,8 +510,7 @@ func copyLibFiles(localDependenciesDirectory string, localLibDirectory string) e for _, dependencyJar := range fileNames { source := path.Join(localDependenciesDirectory, dependencyJar) destination := path.Join(localLibDirectory, dependencyJar) - _, err = util.CopyFile(source, destination) - if err != nil { + if _, err = util.CopyFile(source, destination); err != nil { return err } } @@ -540,8 +533,7 @@ func copyAppFile(localDependenciesDirectory string, localAppDirectory string) er if strings.HasPrefix(dependencyJar, "camel-k-integration-") { source := path.Join(localDependenciesDirectory, dependencyJar) destination := path.Join(localAppDirectory, dependencyJar) - _, err = util.CopyFile(source, destination) - if err != nil { + if _, err = util.CopyFile(source, destination); err != nil { return err } } diff --git a/pkg/cmd/local_util_container.go b/pkg/cmd/local_util_container.go index e03824b7cc..e2bcdd1911 100644 --- a/pkg/cmd/local_util_container.go +++ b/pkg/cmd/local_util_container.go @@ -84,11 +84,20 @@ func setDockerEnvVars(envVars []string) { } func createAndBuildBaseImage(ctx context.Context, stdout, stderr io.Writer) error { + // This ensures the Dockerfile for the base image will not end up in an undesired location. + if docker.BaseWorkingDirectory == "" { + return errors.New("base directory that holds the base image Dockerfile has not been set correctly") + } + // Create the base image Docker file. if err := docker.CreateBaseImageDockerFile(); err != nil { return err } + return buildBaseImage(ctx, stdout, stderr) +} + +func buildBaseImage(ctx context.Context, stdout, stderr io.Writer) error { // Get the Docker command arguments for building the base image and create the command. args := docker.BuildBaseImageArgs() cmd := exec.CommandContext(ctx, "docker", args...) @@ -108,15 +117,8 @@ func createAndBuildBaseImage(ctx context.Context, stdout, stderr io.Writer) erro return nil } -func createAndBuildIntegrationImage(ctx context.Context, containerRegistry string, justBaseImage bool, image string, - propertyFiles []string, dependencies []string, routes []string, startsFromLocalFolder bool, stdout, stderr io.Writer) error { - // This ensures the Dockerfile for the base image will not end up in an undesired location. - if docker.BaseWorkingDirectory == "" { - return errors.New("base directory that holds the base image Dockerfile has not been set correctly") - } - +func setupDockerRegistry(containerRegistry string, image string, justBaseImage bool) error { docker.RegistryName = containerRegistry - // If we build a normal image, i.e. not the base image, we need to parse // the location where images will be pushed. if !justBaseImage { @@ -124,10 +126,19 @@ func createAndBuildIntegrationImage(ctx context.Context, containerRegistry strin if err != nil { return err } - docker.RegistryName = registryName } + return nil +} + +func createAndBuildIntegrationImage(ctx context.Context, containerRegistry string, justBaseImage bool, image string, + propertyFiles []string, dependencies []string, routes []string, startsFromLocalFolder bool, + stdout, stderr io.Writer) error { + if err := setupDockerRegistry(containerRegistry, image, justBaseImage); err != nil { + return err + } + // Create the Dockerfile and build the base image. if err := createAndBuildBaseImage(ctx, stdout, stderr); err != nil { return err @@ -179,6 +190,11 @@ func createAndBuildIntegrationImage(ctx context.Context, containerRegistry strin return err } + return buildIntegrationImage(ctx, image, startsFromLocalFolder, stdout, stderr) +} + +func buildIntegrationImage(ctx context.Context, image string, startsFromLocalFolder bool, + stdout, stderr io.Writer) error { // Get the Docker command arguments for building the base image and create the command. args := docker.BuildIntegrationImageArgs(image, MavenWorkingDirectory) cmd := exec.CommandContext(ctx, "docker", args...) diff --git a/pkg/util/docker/docker.go b/pkg/util/docker/docker.go index a053434c9d..eca77307f0 100644 --- a/pkg/util/docker/docker.go +++ b/pkg/util/docker/docker.go @@ -39,8 +39,7 @@ func CreateBaseImageDockerFile() error { // Write /Dockerfile baseDockerFilePath := path.Join(BaseWorkingDirectory, "Dockerfile") - err := util.WriteToFile(baseDockerFilePath, strings.Join(dockerFile, "\n")) - if err != nil { + if err := util.WriteToFile(baseDockerFilePath, strings.Join(dockerFile, "\n")); err != nil { return err } diff --git a/pkg/util/docker/docker_base.go b/pkg/util/docker/docker_base.go index b1e032fbe0..5fba82e950 100644 --- a/pkg/util/docker/docker_base.go +++ b/pkg/util/docker/docker_base.go @@ -40,7 +40,7 @@ var IntegrationWorkingDirectory = "" var NetworkName = "host" // Internal variables. -var ( +const ( dockerEndpointSeparator = "/" containerFileSeparator = "/" latestTag = "latest" @@ -174,7 +174,7 @@ func GetFullDockerImage(dockerImageName string, tag string) string { return strings.Join(fullImagePath, dockerEndpointSeparator) } -// GetBaseImagePath --. +// GetBaseImagePath returns Docker base image path. func GetBaseImagePath() string { return RegistryName + dockerEndpointSeparator + BaseImageName } From bddb19dc46882b8b6b6b968e9d189c0cd8771b4e Mon Sep 17 00:00:00 2001 From: Tadayoshi Sato Date: Fri, 29 Jul 2022 14:10:52 +0900 Subject: [PATCH 5/9] chore(cli): further refactor kamel local cmds --- pkg/cmd/local_build.go | 14 ++- pkg/cmd/local_inspect.go | 11 +- pkg/cmd/local_run.go | 183 +++++++++++++++++--------------- pkg/cmd/local_util.go | 69 ++++++------ pkg/cmd/local_util_container.go | 5 +- pkg/util/util.go | 15 --- 6 files changed, 147 insertions(+), 150 deletions(-) diff --git a/pkg/cmd/local_build.go b/pkg/cmd/local_build.go index bc506c27b4..fba6d4d823 100644 --- a/pkg/cmd/local_build.go +++ b/pkg/cmd/local_build.go @@ -58,8 +58,10 @@ func newCmdLocalBuild(localCmdOptions *LocalCmdOptions) (*cobra.Command, *localB } cmd.Flags().Bool("base-image", false, "Build base image used as a starting point for any integration.") - cmd.Flags().Bool("dependencies-only", false, "Only output the integration dependencies. The integration-directory flag must be set.") - cmd.Flags().String("container-registry", "", "Registry that holds intermediate images. This flag should only be used in conjunction with the base-image flag.") + cmd.Flags().Bool("dependencies-only", false, + "Only output the integration dependencies. The integration-directory flag must be set.") + cmd.Flags().String("container-registry", "", + "Registry that holds intermediate images. This flag should only be used in conjunction with the base-image flag.") cmd.Flags().String("image", "", "Full path to integration image including registry.") cmd.Flags().String("integration-directory", "", "Directory to hold local integration files.") cmd.Flags().StringArray("property-file", nil, "Add a property file to the integration.") @@ -84,7 +86,7 @@ type localBuildCmdOptions struct { func (o *localBuildCmdOptions) validate(args []string) error { // Validate integration files. if len(args) > 0 { - if err := validateIntegrationFiles(args); err != nil { + if err := validateFiles(args); err != nil { return err } } @@ -149,11 +151,7 @@ func (o *localBuildCmdOptions) init(args []string) error { } } - if err := createMavenWorkingDirectory(); err != nil { - return err - } - - return nil + return createMavenWorkingDirectory() } func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { diff --git a/pkg/cmd/local_inspect.go b/pkg/cmd/local_inspect.go index 1c180d56bd..e5df5bd7bf 100644 --- a/pkg/cmd/local_inspect.go +++ b/pkg/cmd/local_inspect.go @@ -18,6 +18,7 @@ limitations under the License. package cmd import ( + "errors" "fmt" "github.com/spf13/cobra" @@ -71,7 +72,12 @@ type localInspectCmdOptions struct { } func (o *localInspectCmdOptions) validate(args []string) error { - if err := validateIntegrationFiles(args); err != nil { + // If no source files have been provided there is nothing to inspect. + if len(args) == 0 { + return errors.New("no integration files have been provided") + } + + if err := validateFiles(args); err != nil { return err } @@ -92,8 +98,7 @@ func (o *localInspectCmdOptions) run(cmd *cobra.Command, args []string) error { return err } - err = outputDependencies(dependencies, o.OutputFormat, cmd) - if err != nil { + if err = outputDependencies(dependencies, o.OutputFormat, cmd); err != nil { return err } diff --git a/pkg/cmd/local_run.go b/pkg/cmd/local_run.go index 62e53205a1..d424a8e8c7 100644 --- a/pkg/cmd/local_run.go +++ b/pkg/cmd/local_run.go @@ -74,7 +74,8 @@ func newCmdLocalRun(localCmdOptions *LocalCmdOptions) (*cobra.Command, *localRun cmd.Flags().Bool("containerize", false, "Run integration in a local container.") cmd.Flags().String("image", "", "Full path to integration image including registry.") cmd.Flags().String("network", "", "Custom network name to be used by the underlying Docker command.") - cmd.Flags().String("integration-directory", "", "Directory which holds the locally built integration and is the result of a local build action.") + cmd.Flags().String("integration-directory", "", + "Directory which holds the locally built integration and is the result of a local build action.") cmd.Flags().StringArrayP("env", "e", nil, "Flag to specify an environment variable [--env VARIABLE=value].") cmd.Flags().StringArray("property-file", nil, "Add a property file to the integration.") cmd.Flags().StringArrayP("property", "p", nil, "Add a Camel property to the integration.") @@ -99,7 +100,12 @@ func (o *localRunCmdOptions) validate(args []string) error { // Validate integration files when no image is provided and we are // not running an already locally-built integration. if o.Image == "" && o.IntegrationDirectory == "" { - if err := validateIntegrationFiles(args); err != nil { + if len(args) == 0 { + return errors.New("no integration files have been provided") + } + + // Validate integration files. + if err := validateFiles(args); err != nil { return err } } @@ -144,129 +150,132 @@ func (o *localRunCmdOptions) run(cmd *cobra.Command, args []string) error { // If local run is provided with an image name, it will just run the image locally and exit. if o.Image != "" && !o.Containerize { // Run image locally. - if err := runIntegrationImage(o.Context, o.Image, cmd.OutOrStdout(), cmd.ErrOrStderr()); err != nil { + return runIntegrationImage(o.Context, o.Image, cmd.OutOrStdout(), cmd.ErrOrStderr()) + } + + dependencies, err := o.processDependencies(args) + if err != nil { + return err + } + propertyFiles, err := o.processPropertyFiles() + if err != nil { + return err + } + routes, err := o.processRoutes(args) + if err != nil { + return err + } + + if o.Containerize { + // If this is a containerized local run, create, build and run the container image. + if err := createAndBuildIntegrationImage(o.Context, "", false, o.Image, + propertyFiles, dependencies, routes, o.IntegrationDirectory != "", + cmd.OutOrStdout(), cmd.ErrOrStderr()); err != nil { return err } - return nil + // Run integration image. + return runIntegrationImage(o.Context, o.Image, cmd.OutOrStdout(), cmd.ErrOrStderr()) } - hasIntegrationDir := o.IntegrationDirectory != "" + // Run integration locally. + return RunLocalIntegrationRunCommand(o.Context, propertyFiles, dependencies, routes, o.getPropertiesDir(), + cmd.OutOrStdout(), cmd.ErrOrStderr()) +} - var dependencies []string - if hasIntegrationDir { - // Fetch local dependencies - localBuildDependencies, err := getLocalBuildDependencies(o.IntegrationDirectory) - if err != nil { - return err - } - dependencies = localBuildDependencies +func (o *localRunCmdOptions) processDependencies(args []string) ([]string, error) { + if o.IntegrationDirectory == "" { + return getDependencies(o.Context, args, o.Dependencies, o.MavenRepositories, true) + } - // Local dependencies directory - localDependenciesDirectory := getCustomDependenciesDir(o.IntegrationDirectory) + // Set up on the integration directory - // The quarkus application files need to be at a specific location i.e.: - // /../quarkus/quarkus-application.dat - // /../quarkus/generated-bytecode.jar - localQuarkusDir := getCustomQuarkusDir(o.IntegrationDirectory) - err = copyQuarkusAppFiles(localDependenciesDirectory, localQuarkusDir) - if err != nil { - return err - } + // Fetch local dependencies + dependencies, err := getLocalBuildDependencies(o.IntegrationDirectory) + if err != nil { + return nil, err + } + if err := o.setupDependenciesForQuarkusRun(); err != nil { + return dependencies, err + } - // The dependency jar files need to be at a specific location i.e.: - // /../lib/main/*.jar - localLibDirectory := getCustomLibDir(o.IntegrationDirectory) - err = copyLibFiles(localDependenciesDirectory, localLibDirectory) - if err != nil { - return err - } + return dependencies, nil +} - // The Camel K jar file needs to be at a specific location i.e.: - // /../app/camel-k-integration-X.X.X{-SNAPSHOT}.jar - localAppDirectory := getCustomAppDir(o.IntegrationDirectory) - err = copyAppFile(localDependenciesDirectory, localAppDirectory) - if err != nil { - return err - } - } else { - computedDependencies, err := getDependencies(o.Context, args, o.Dependencies, o.MavenRepositories, true) - if err != nil { - return err - } - dependencies = computedDependencies +// setupDependenciesForQuarkusRun sets up resources under the integration directory for running Quarkus app. +func (o *localRunCmdOptions) setupDependenciesForQuarkusRun() error { + // Local dependencies directory + localDependenciesDir := getCustomDependenciesDir(o.IntegrationDirectory) + + // The quarkus application files need to be at a specific location i.e.: + // /../quarkus/quarkus-application.dat + // /../quarkus/generated-bytecode.jar + localQuarkusDir := getCustomQuarkusDir(o.IntegrationDirectory) + if err := copyQuarkusAppFiles(localDependenciesDir, localQuarkusDir); err != nil { + return err } - // Manage integration properties which may come from files or CLI. - propertyFiles := o.PropertyFiles - if hasIntegrationDir { - localBuildPropertyFiles, err := getLocalBuildProperties(o.IntegrationDirectory) - if err != nil { - return err - } - propertyFiles = localBuildPropertyFiles + // The dependency jar files need to be at a specific location i.e.: + // /../lib/main/*.jar + localLibDir := getCustomLibDir(o.IntegrationDirectory) + if err := copyLibFiles(localDependenciesDir, localLibDir); err != nil { + return err } - updatedPropertyFiles, err := updateIntegrationProperties(o.Properties, propertyFiles, hasIntegrationDir) - if err != nil { + // The Camel K jar file needs to be at a specific location i.e.: + // /../app/camel-k-integration-X.X.X{-SNAPSHOT}.jar + localAppDir := getCustomAppDir(o.IntegrationDirectory) + if err := copyAppFile(localDependenciesDir, localAppDir); err != nil { return err } - propertyFiles = updatedPropertyFiles - routes := args + return nil +} + +// processPropertyFiles processes integration properties which may come from files or CLI. +func (o *localRunCmdOptions) processPropertyFiles() ([]string, error) { + propertyFiles := o.PropertyFiles + hasIntegrationDir := o.IntegrationDirectory != "" if hasIntegrationDir { - localBuildRoutes, err := getLocalBuildRoutes(o.IntegrationDirectory) + localPropertyFiles, err := getLocalBuildProperties(o.IntegrationDirectory) if err != nil { - return err + return nil, err } - routes = localBuildRoutes + propertyFiles = localPropertyFiles } - // If this is a containerized local run, create, build and run the container image. - if o.Containerize { - if err := createAndBuildIntegrationImage(o.Context, "", false, o.Image, - propertyFiles, dependencies, routes, hasIntegrationDir, - cmd.OutOrStdout(), cmd.ErrOrStderr()); err != nil { - return err - } + return updateIntegrationProperties(o.Properties, propertyFiles, hasIntegrationDir) +} - // Run integration image. - err = runIntegrationImage(o.Context, o.Image, cmd.OutOrStdout(), cmd.ErrOrStderr()) - if err != nil { - return err - } - } else { - propertiesDir := getLocalPropertiesDir() - if hasIntegrationDir { - propertiesDir = getCustomPropertiesDir(o.IntegrationDirectory) - } +func (o *localRunCmdOptions) processRoutes(args []string) ([]string, error) { + if o.IntegrationDirectory == "" { + return args, nil + } - // Run integration locally. - err := RunLocalIntegrationRunCommand(o.Context, propertyFiles, dependencies, routes, propertiesDir, cmd.OutOrStdout(), cmd.ErrOrStderr()) - if err != nil { - return err - } + return getLocalBuildRoutes(o.IntegrationDirectory) +} + +func (o *localRunCmdOptions) getPropertiesDir() string { + if o.IntegrationDirectory == "" { + return getLocalPropertiesDir() } - return nil + return getCustomPropertiesDir(o.IntegrationDirectory) } func (o *localRunCmdOptions) deinit() error { if o.Containerize { - err := deleteDockerBaseWorkingDirectory() - if err != nil { + if err := deleteDockerBaseWorkingDirectory(); err != nil { return err } - err = deleteDockerWorkingDirectory() - if err != nil { + if err := deleteDockerWorkingDirectory(); err != nil { return err } } if o.IntegrationDirectory != "" { - err := deleteLocalIntegrationDirs(o.IntegrationDirectory) - if err != nil { + if err := deleteLocalIntegrationDirs(o.IntegrationDirectory); err != nil { return err } } diff --git a/pkg/cmd/local_util.go b/pkg/cmd/local_util.go index bc0d266194..166489a7a1 100644 --- a/pkg/cmd/local_util.go +++ b/pkg/cmd/local_util.go @@ -19,6 +19,7 @@ package cmd import ( "context" + "encoding/json" "fmt" "io/ioutil" "os" @@ -236,8 +237,7 @@ func createCamelCatalog(ctx context.Context) (*camel.RuntimeCatalog, error) { func outputDependencies(dependencies []string, format string, cmd *cobra.Command) error { if format != "" { - err := printDependencies(format, dependencies, cmd) - if err != nil { + if err := printDependencies(format, dependencies, cmd); err != nil { return err } } else { @@ -254,23 +254,38 @@ func outputDependencies(dependencies []string, format string, cmd *cobra.Command func printDependencies(format string, dependencies []string, cmd *cobra.Command) error { switch format { case "yaml": - data, err := util.DependenciesToYAML(dependencies) + data, err := dependenciesToYAML(dependencies) if err != nil { return err } fmt.Fprint(cmd.OutOrStdout(), string(data)) case "json": - data, err := util.DependenciesToJSON(dependencies) + data, err := dependenciesToJSON(dependencies) if err != nil { return err } fmt.Fprint(cmd.OutOrStdout(), string(data)) default: - return errors.New("unknown output format: " + format) + return errors.Errorf("unknown output format: %s", format) } return nil } +func dependenciesToJSON(list []string) ([]byte, error) { + jsondata := map[string]interface{}{} + jsondata["dependencies"] = list + return json.Marshal(jsondata) +} + +func dependenciesToYAML(list []string) ([]byte, error) { + data, err := dependenciesToJSON(list) + if err != nil { + return nil, err + } + + return util.JSONToYAML(data) +} + func validateFile(file string) error { fileExists, err := util.FileExists(file) if err != nil { @@ -310,20 +325,6 @@ func validateDependencies(dependencies []string) error { return nil } -func validateIntegrationFiles(args []string) error { - // If no source files have been provided there is nothing to inspect. - if len(args) == 0 { - return errors.New("no integration files have been provided") - } - - // Validate integration files. - if err := validateFiles(args); err != nil { - return err - } - - return nil -} - func validatePropertyFiles(propertyFiles []string) error { for _, fileName := range propertyFiles { if err := validatePropertyFile(fileName); err != nil { @@ -472,21 +473,21 @@ func copyIntegrationFilesToDirectory(files []string, directory string) ([]string return relocatedFilesList, nil } -func copyQuarkusAppFiles(localDependenciesDirectory string, localQuarkusDir string) error { +func copyQuarkusAppFiles(dependenciesDir string, quarkusDir string) error { // Create directory if one does not already exist - if err := util.CreateDirectory(localQuarkusDir); err != nil { + if err := util.CreateDirectory(quarkusDir); err != nil { return err } // Transfer all files with a .dat extension and all files with a *-bytecode.jar suffix. - files, err := getRegularFilesInDir(localDependenciesDirectory, false) + files, err := getRegularFilesInDir(dependenciesDir, false) if err != nil { return err } for _, file := range files { if strings.HasSuffix(file, ".dat") || strings.HasSuffix(file, "-bytecode.jar") { - source := path.Join(localDependenciesDirectory, file) - destination := path.Join(localQuarkusDir, file) + source := path.Join(dependenciesDir, file) + destination := path.Join(quarkusDir, file) if _, err = util.CopyFile(source, destination); err != nil { return err } @@ -496,20 +497,20 @@ func copyQuarkusAppFiles(localDependenciesDirectory string, localQuarkusDir stri return nil } -func copyLibFiles(localDependenciesDirectory string, localLibDirectory string) error { +func copyLibFiles(dependenciesDir string, libDir string) error { // Create directory if one does not already exist - if err := util.CreateDirectory(localLibDirectory); err != nil { + if err := util.CreateDirectory(libDir); err != nil { return err } - fileNames, err := getRegularFilesInDir(localDependenciesDirectory, false) + fileNames, err := getRegularFilesInDir(dependenciesDir, false) if err != nil { return err } for _, dependencyJar := range fileNames { - source := path.Join(localDependenciesDirectory, dependencyJar) - destination := path.Join(localLibDirectory, dependencyJar) + source := path.Join(dependenciesDir, dependencyJar) + destination := path.Join(libDir, dependencyJar) if _, err = util.CopyFile(source, destination); err != nil { return err } @@ -518,21 +519,21 @@ func copyLibFiles(localDependenciesDirectory string, localLibDirectory string) e return nil } -func copyAppFile(localDependenciesDirectory string, localAppDirectory string) error { +func copyAppFile(dependenciesDir string, appDir string) error { // Create directory if one does not already exist - if err := util.CreateDirectory(localAppDirectory); err != nil { + if err := util.CreateDirectory(appDir); err != nil { return err } - fileNames, err := getRegularFilesInDir(localDependenciesDirectory, false) + fileNames, err := getRegularFilesInDir(dependenciesDir, false) if err != nil { return err } for _, dependencyJar := range fileNames { if strings.HasPrefix(dependencyJar, "camel-k-integration-") { - source := path.Join(localDependenciesDirectory, dependencyJar) - destination := path.Join(localAppDirectory, dependencyJar) + source := path.Join(dependenciesDir, dependencyJar) + destination := path.Join(appDir, dependencyJar) if _, err = util.CopyFile(source, destination); err != nil { return err } diff --git a/pkg/cmd/local_util_container.go b/pkg/cmd/local_util_container.go index e2bcdd1911..a10c49025f 100644 --- a/pkg/cmd/local_util_container.go +++ b/pkg/cmd/local_util_container.go @@ -190,11 +190,10 @@ func createAndBuildIntegrationImage(ctx context.Context, containerRegistry strin return err } - return buildIntegrationImage(ctx, image, startsFromLocalFolder, stdout, stderr) + return buildIntegrationImage(ctx, image, stdout, stderr) } -func buildIntegrationImage(ctx context.Context, image string, startsFromLocalFolder bool, - stdout, stderr io.Writer) error { +func buildIntegrationImage(ctx context.Context, image string, stdout, stderr io.Writer) error { // Get the Docker command arguments for building the base image and create the command. args := docker.BuildIntegrationImageArgs(image, MavenWorkingDirectory) cmd := exec.CommandContext(ctx, "docker", args...) diff --git a/pkg/util/util.go b/pkg/util/util.go index 878c5913d2..25ca86517a 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -423,21 +423,6 @@ func CopyMap(source map[string]string) map[string]string { return dest } -func DependenciesToJSON(list []string) ([]byte, error) { - jsondata := map[string]interface{}{} - jsondata["dependencies"] = list - return json.Marshal(jsondata) -} - -func DependenciesToYAML(list []string) ([]byte, error) { - data, err := DependenciesToJSON(list) - if err != nil { - return nil, err - } - - return JSONToYAML(data) -} - func JSONToYAML(src []byte) ([]byte, error) { mapdata, err := JSONToMap(src) if err != nil { From b84c53f4ea29546b5c9f144d4bd9c4f4e99a6ad9 Mon Sep 17 00:00:00 2001 From: Tadayoshi Sato Date: Fri, 29 Jul 2022 15:05:01 +0900 Subject: [PATCH 6/9] chore(cli): further refactor kamel local cmds --- pkg/cmd/local_run.go | 2 +- pkg/cmd/local_util_container.go | 103 +++++++++++++++++++++++- pkg/cmd/util_commands.go | 134 -------------------------------- 3 files changed, 103 insertions(+), 136 deletions(-) delete mode 100644 pkg/cmd/util_commands.go diff --git a/pkg/cmd/local_run.go b/pkg/cmd/local_run.go index d424a8e8c7..74027a11c3 100644 --- a/pkg/cmd/local_run.go +++ b/pkg/cmd/local_run.go @@ -179,7 +179,7 @@ func (o *localRunCmdOptions) run(cmd *cobra.Command, args []string) error { } // Run integration locally. - return RunLocalIntegrationRunCommand(o.Context, propertyFiles, dependencies, routes, o.getPropertiesDir(), + return runLocalIntegration(o.Context, propertyFiles, dependencies, routes, o.getPropertiesDir(), cmd.OutOrStdout(), cmd.ErrOrStderr()) } diff --git a/pkg/cmd/local_util_container.go b/pkg/cmd/local_util_container.go index a10c49025f..109ca030da 100644 --- a/pkg/cmd/local_util_container.go +++ b/pkg/cmd/local_util_container.go @@ -180,7 +180,7 @@ func createAndBuildIntegrationImage(ctx context.Context, containerRegistry strin // Get integration run command to be run inside the container. This means the command // has to be created with the paths which will be valid inside the container. - containerCmd, err := GetContainerIntegrationRunCommand(ctx, propertyFiles, dependencies, routes, stdout, stderr) + containerCmd, err := getContainerIntegrationRunCommand(ctx, propertyFiles, dependencies, routes, stdout, stderr) if err != nil { return err } @@ -245,3 +245,104 @@ func runIntegrationImage(ctx context.Context, image string, stdout, stderr io.Wr return nil } + +// getContainerIntegrationRunCommand returns the integration command which will be run inside the container. +func getContainerIntegrationRunCommand(ctx context.Context, properties []string, dependencies []string, routes []string, + stdout, stderr io.Writer) (*exec.Cmd, error) { + // All paths need to be valid container paths. + // Update property file paths. + containerProperties := docker.ContainerizeFilePaths(properties, docker.GetContainerPropertiesDir()) + containerDependencies := docker.ContainerizeDependencyPaths(dependencies, docker.GetContainerDependenciesDir()) + containerRoutes := docker.ContainerizeFilePaths(routes, docker.GetContainerRoutesDir()) + + return assembleIntegrationRunCommand(ctx, containerProperties, containerDependencies, containerRoutes, + docker.GetContainerPropertiesDir(), stdout, stderr, false) +} + +func runLocalIntegration(ctx context.Context, properties []string, dependencies []string, routes []string, + propertiesDir string, stdout, stderr io.Writer) error { + cmd, err := assembleIntegrationRunCommand(ctx, properties, dependencies, routes, + propertiesDir, stdout, stderr, true) + if err != nil { + return err + } + + // Output command we are about to run. + fmt.Fprintln(cmd.Stdout, "Executing:", strings.Join(cmd.Args, " ")) + + // Run integration locally. + return cmd.Run() +} + +func assembleIntegrationRunCommand(ctx context.Context, properties []string, dependencies []string, routes []string, + propertiesDir string, stdout, stderr io.Writer, local bool) (*exec.Cmd, error) { + // Create classpath value. + classpathValue := assembleClasspathArgValue(properties, dependencies, routes) + + // Create java command that runs the integration. + javaCmd := "java" + + // Create java command arguments. + args := make([]string, 0) + args = append(args, "-cp") + args = append(args, classpathValue) + args = append(args, "io.quarkus.bootstrap.runner.QuarkusEntryPoint") + + cmd := exec.CommandContext(ctx, javaCmd, args...) + + // Add directory where the properties files reside. The directory is the local properties directory + // or the properties directory inside the container. + cmd.Env = append(cmd.Env, "CAMEL_K_CONF_D="+propertiesDir) + + // Add files to the command line under the CAMEL_K_ROUTES flag. + cmd.Env = append(cmd.Env, "CAMEL_K_ROUTES="+strings.Join(formatRoutes(routes), ",")) + + // Add any lazily evaluated environment variables. + if local { + // If we are running locally then this is as late as we can evaluate the + // lazy environment variables since we are going to run the command + // immediately after the generation of these arguments. + setEnvVars, err := util.EvaluateCLIAndLazyEnvVars() + if err != nil { + return nil, err + } + cmd.Env = append(cmd.Env, setEnvVars...) + } else { + // If we are running in containerized or just building an image, we should + // not evaluate the variables at this point since we are only generating the + // run command and not actually running it. + for _, lazyEnvVar := range util.ListOfLazyEvaluatedEnvVars { + cmd.Env = append(cmd.Env, lazyEnvVar+"={{env:"+lazyEnvVar+"}}") + } + } + + // Set stdout and stderr. + cmd.Stderr = stderr + cmd.Stdout = stdout + + return cmd, nil +} + +func assembleClasspathArgValue(properties []string, dependencies []string, routes []string) string { + classpathContents := []string{} + classpathContents = append(classpathContents, properties...) + classpathContents = append(classpathContents, routes...) + classpathContents = append(classpathContents, dependencies...) + return strings.Join(classpathContents, string(os.PathListSeparator)) +} + +func formatRoutes(files []string) []string { + routes := []string{} + for _, route := range files { + // Split route path. + a := strings.Split(route, ".") + + // Extract extension. + extension := a[len(a)-1] + + // Add file with extension. + routes = append(routes, "file:"+route+"?language="+extension) + } + + return routes +} diff --git a/pkg/cmd/util_commands.go b/pkg/cmd/util_commands.go deleted file mode 100644 index 7f0252a3f5..0000000000 --- a/pkg/cmd/util_commands.go +++ /dev/null @@ -1,134 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You under the Apache License, Version 2.0 -(the "License"); you may not use this file except in compliance with -the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cmd - -import ( - "context" - "fmt" - "io" - "os" - "os/exec" - "strings" - - "github.com/apache/camel-k/pkg/util" - "github.com/apache/camel-k/pkg/util/docker" -) - -func formatRoutes(files []string) []string { - routes := []string{} - for _, route := range files { - // Split route path. - a := strings.Split(route, ".") - - // Extract extension. - extension := a[len(a)-1] - - // Add file with extension. - routes = append(routes, "file:"+route+"?language="+extension) - } - - return routes -} - -func assembleClasspathArgValue(properties []string, dependencies []string, routes []string) string { - classpathContents := []string{} - classpathContents = append(classpathContents, properties...) - classpathContents = append(classpathContents, routes...) - classpathContents = append(classpathContents, dependencies...) - return strings.Join(classpathContents, string(os.PathListSeparator)) -} - -func assembleIntegrationRunCommand(ctx context.Context, properties []string, dependencies []string, routes []string, propertiesDir string, stdout, stderr io.Writer, local bool) (*exec.Cmd, error) { - // Create classpath value. - classpathValue := assembleClasspathArgValue(properties, dependencies, routes) - - // Create java command that runs the integration. - javaCmd := "java" - - // Create java command arguments. - args := make([]string, 0) - args = append(args, "-cp") - args = append(args, classpathValue) - args = append(args, "io.quarkus.bootstrap.runner.QuarkusEntryPoint") - - cmd := exec.CommandContext(ctx, javaCmd, args...) - - // Add directory where the properties files reside. The directory is the local properties directory - // or the properties directory inside the container. - cmd.Env = append(cmd.Env, "CAMEL_K_CONF_D="+propertiesDir) - - // Add files to the command line under the CAMEL_K_ROUTES flag. - cmd.Env = append(cmd.Env, "CAMEL_K_ROUTES="+strings.Join(formatRoutes(routes), ",")) - - // Add any lazily evaluated environment variables. - if local { - // If we are running locally then this is as late as we can evaluate the - // lazy environment variables since we are going to run the command - // immediately after the generation of these arguments. - setEnvVars, err := util.EvaluateCLIAndLazyEnvVars() - if err != nil { - return nil, err - } - cmd.Env = append(cmd.Env, setEnvVars...) - } else { - // If we are running in containerized or just building an image, we should - // not evaluate the variables at this point since we are only generating the - // run command and not actually running it. - for _, lazyEnvVar := range util.ListOfLazyEvaluatedEnvVars { - cmd.Env = append(cmd.Env, lazyEnvVar+"={{env:"+lazyEnvVar+"}}") - } - } - - // Set stdout and stderr. - cmd.Stderr = stderr - cmd.Stdout = stdout - - return cmd, nil -} - -// RunLocalIntegrationRunCommand --. -func RunLocalIntegrationRunCommand(ctx context.Context, properties []string, dependencies []string, routes []string, propertiesDir string, stdout, stderr io.Writer) error { - cmd, err := assembleIntegrationRunCommand(ctx, properties, dependencies, routes, propertiesDir, stdout, stderr, true) - if err != nil { - return err - } - - // Output command we are about to run. - fmt.Fprintln(cmd.Stdout, "Executing:", strings.Join(cmd.Args, " ")) - - // Run integration locally. - err = cmd.Run() - if err != nil { - return err - } - - return nil -} - -// GetContainerIntegrationRunCommand --. -func GetContainerIntegrationRunCommand(ctx context.Context, properties []string, dependencies []string, routes []string, stdout, stderr io.Writer) (*exec.Cmd, error) { - // This is the integration command which will be run inside the container. Therefore all paths need to - // be valid container paths. - - // Update property file paths. - containerProperties := docker.ContainerizeFilePaths(properties, docker.GetContainerPropertiesDir()) - containerDependencies := docker.ContainerizeDependencyPaths(dependencies, docker.GetContainerDependenciesDir()) - containerRoutes := docker.ContainerizeFilePaths(routes, docker.GetContainerRoutesDir()) - - return assembleIntegrationRunCommand(ctx, containerProperties, containerDependencies, containerRoutes, docker.GetContainerPropertiesDir(), stdout, stderr, false) -} From f9da1bcd9aa43c0f5b21fb0c1624fbb5ab046143 Mon Sep 17 00:00:00 2001 From: Tadayoshi Sato Date: Fri, 29 Jul 2022 15:16:06 +0900 Subject: [PATCH 7/9] fix(cli): more user-friendly error messages for kamel local subcommands Fix #3028 --- pkg/cmd/local.go | 15 ++++++- pkg/cmd/local_build.go | 97 ++++++++++++++++++++++++++-------------- pkg/cmd/local_inspect.go | 6 +-- pkg/cmd/local_run.go | 48 ++++++++++---------- pkg/cmd/local_util.go | 7 +-- 5 files changed, 105 insertions(+), 68 deletions(-) diff --git a/pkg/cmd/local.go b/pkg/cmd/local.go index 65163bfa51..c5616d5ed9 100644 --- a/pkg/cmd/local.go +++ b/pkg/cmd/local.go @@ -24,6 +24,14 @@ import ( "github.com/spf13/cobra" ) +// Usage descritions of common flags that are shared across some of the subcommands. +const ( + usageImage = `Full path to integration image including registry, e.g. "docker.io/user/app"` + usageIntegrationDirectory = "Directory to hold local integration files" + usagePropertyFile = "Add a property file to the integration" + usageProperty = "Add a Camel property to the integration" +) + // newCmdLocal -- Add local kamel subcommand with several other subcommands of its own. func newCmdLocal(rootCmdOptions *RootCmdOptions) (*cobra.Command, *LocalCmdOptions) { options := LocalCmdOptions{ @@ -41,6 +49,8 @@ func newCmdLocal(rootCmdOptions *RootCmdOptions) (*cobra.Command, *LocalCmdOptio } cmd.PersistentFlags().StringArrayVarP(&options.Dependencies, "dependency", "d", nil, usageDependency) + cmd.PersistentFlags().StringArrayVar(&options.MavenRepositories, "maven-repository", nil, + "Use a maven repository") // hidden flags for compatibility with kamel run cmd.PersistentFlags().StringArrayVarP(&options.Traits, "trait", "t", nil, "") @@ -57,8 +67,9 @@ func newCmdLocal(rootCmdOptions *RootCmdOptions) (*cobra.Command, *LocalCmdOptio type LocalCmdOptions struct { *RootCmdOptions - Dependencies []string `mapstructure:"dependencies"` - Traits []string `mapstructure:"traits"` + Dependencies []string `mapstructure:"dependencies"` + MavenRepositories []string `mapstructure:"maven-repositories"` + Traits []string `mapstructure:"traits"` } func (o *LocalCmdOptions) persistentPreRun(cmd *cobra.Command, args []string) error { diff --git a/pkg/cmd/local_build.go b/pkg/cmd/local_build.go index fba6d4d823..cf36c9d858 100644 --- a/pkg/cmd/local_build.go +++ b/pkg/cmd/local_build.go @@ -37,7 +37,7 @@ func newCmdLocalBuild(localCmdOptions *LocalCmdOptions) (*cobra.Command, *localB Long: `Build integration images locally for containerized integrations.`, PreRunE: decode(&options), RunE: func(cmd *cobra.Command, args []string) error { - if err := options.validate(args); err != nil { + if err := options.validate(cmd, args); err != nil { return err } if err := options.init(args); err != nil { @@ -57,16 +57,15 @@ func newCmdLocalBuild(localCmdOptions *LocalCmdOptions) (*cobra.Command, *localB }, } - cmd.Flags().Bool("base-image", false, "Build base image used as a starting point for any integration.") + cmd.Flags().Bool("base-image", false, "Build base image used as a starting point for any integration") cmd.Flags().Bool("dependencies-only", false, "Only output the integration dependencies. The integration-directory flag must be set.") cmd.Flags().String("container-registry", "", "Registry that holds intermediate images. This flag should only be used in conjunction with the base-image flag.") - cmd.Flags().String("image", "", "Full path to integration image including registry.") - cmd.Flags().String("integration-directory", "", "Directory to hold local integration files.") - cmd.Flags().StringArray("property-file", nil, "Add a property file to the integration.") - cmd.Flags().StringArrayP("property", "p", nil, "Add a Camel property to the integration.") - cmd.Flags().StringArray("maven-repository", nil, "Use a maven repository") + cmd.Flags().String("image", "", usageImage) + cmd.Flags().String("integration-directory", "", usageIntegrationDirectory) + cmd.Flags().StringArray("property-file", nil, usagePropertyFile) + cmd.Flags().StringArrayP("property", "p", nil, usageProperty) return &cmd, &options } @@ -80,50 +79,78 @@ type localBuildCmdOptions struct { IntegrationDirectory string `mapstructure:"integration-directory"` Properties []string `mapstructure:"properties"` PropertyFiles []string `mapstructure:"property-files"` - MavenRepositories []string `mapstructure:"maven-repositories"` } -func (o *localBuildCmdOptions) validate(args []string) error { - // Validate integration files. +func (o *localBuildCmdOptions) validate(cmd *cobra.Command, args []string) error { + if o.BaseImage { + return o.validateBaseImageMode(cmd, args) + } + + return o.validateIntegrationMode(args) +} + +func (o *localBuildCmdOptions) validateBaseImageMode(cmd *cobra.Command, args []string) error { + // Cannot have both integration files and the base image construction enabled. if len(args) > 0 { - if err := validateFiles(args); err != nil { - return err - } + return errors.New("cannot use --base-image with integration files") } - // Validate additional dependencies specified by the user. - if err := validateDependencies(o.Dependencies); err != nil { - return err + // Docker registry must be set. + if o.ContainerRegistry == "" { + return errors.New("--base-image requires --container-registry") } - // Validate properties file. - if err := validateFiles(o.PropertyFiles); err != nil { - return err + // If an integration directory is provided then no base image containerization can be enabled. + if o.IntegrationDirectory != "" { + return errors.New("cannot use --integration-directory with --base-image") } - if o.BaseImage { - // Cannot have both integration files and the base image construction enabled. - if len(args) > 0 { - return errors.New("integration files have been provided and the base image construction is enabled") - } + if o.DependenciesOnly { + return errors.New("cannot use --dependencies-only with --base-image") + } - // Docker registry must be set. - if o.ContainerRegistry == "" { - return errors.New("base image cannot be built because container registry has not been provided") - } + if len(o.Dependencies) > 0 || len(o.PropertyFiles) > 0 || len(o.Properties) > 0 { + fmt.Fprintln(cmd.OutOrStdout(), + "Warning: --dependency, --property, and --property-file are ignored in --base-image mode") + } - // If an integration directory is provided then no base image containerization can be enabled. - if o.IntegrationDirectory != "" { - return errors.New("base image construction does not use integration files") + return nil +} + +func (o *localBuildCmdOptions) validateIntegrationMode(args []string) error { + if len(args) == 0 { + if o.IntegrationDirectory == "" { + return errors.New("either integration files, --integration-directory, or --base-image must be provided") } - } else if o.ContainerRegistry != "" { + } else { + if o.IntegrationDirectory == "" && o.Image == "" { + return errors.New("either --integration-directory or --image must be provided with integration files") + } + } + + if o.ContainerRegistry != "" { // ContainerRegistry should only be specified when building the base image. - return errors.New("cannot specify container registry unless a base integration image is being built") + return errors.New("--container-registry must be used with --base-image") } // The integration directory must be set when only outputting dependencies. if o.DependenciesOnly && o.IntegrationDirectory == "" { - return errors.New("to output dependencies the integration directory flag must be set") + return errors.New("--dependencies-only requires --integration-directory") + } + + // Validate integration files. + if err := validateFiles(args); err != nil { + return err + } + + // Validate additional dependencies specified by the user. + if err := validateDependencies(o.Dependencies); err != nil { + return err + } + + // Validate properties file. + if err := validateFiles(o.PropertyFiles); err != nil { + return err } return nil @@ -206,6 +233,8 @@ func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { // The only case in which we should not execute the integration image creation is when we want to // just output the files that comprise the integration locally. if o.Image == "" { + fmt.Fprintf(cmd.OutOrStdout(), + "Integration directory generated: %s\n", o.IntegrationDirectory) return nil } } diff --git a/pkg/cmd/local_inspect.go b/pkg/cmd/local_inspect.go index e5df5bd7bf..22c6aefb91 100644 --- a/pkg/cmd/local_inspect.go +++ b/pkg/cmd/local_inspect.go @@ -59,16 +59,14 @@ will be generated by calling Maven and then printed in the selected output forma cmd.Flags().Bool("all-dependencies", false, "Enable computation of transitive dependencies.") cmd.Flags().StringP("output", "o", "", "Output format. One of: json|yaml") - cmd.Flags().StringArray("maven-repository", nil, "Use a maven repository") return &cmd, &options } type localInspectCmdOptions struct { *LocalCmdOptions - AllDependencies bool `mapstructure:"all-dependencies"` - OutputFormat string `mapstructure:"output"` - MavenRepositories []string `mapstructure:"maven-repositories"` + AllDependencies bool `mapstructure:"all-dependencies"` + OutputFormat string `mapstructure:"output"` } func (o *localInspectCmdOptions) validate(args []string) error { diff --git a/pkg/cmd/local_run.go b/pkg/cmd/local_run.go index 74027a11c3..467c35076d 100644 --- a/pkg/cmd/local_run.go +++ b/pkg/cmd/local_run.go @@ -23,6 +23,7 @@ import ( "os/signal" "syscall" + "github.com/apache/camel-k/pkg/util" "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -72,14 +73,12 @@ func newCmdLocalRun(localCmdOptions *LocalCmdOptions) (*cobra.Command, *localRun } cmd.Flags().Bool("containerize", false, "Run integration in a local container.") - cmd.Flags().String("image", "", "Full path to integration image including registry.") + cmd.Flags().String("image", "", usageImage) cmd.Flags().String("network", "", "Custom network name to be used by the underlying Docker command.") - cmd.Flags().String("integration-directory", "", - "Directory which holds the locally built integration and is the result of a local build action.") + cmd.Flags().String("integration-directory", "", usageIntegrationDirectory) cmd.Flags().StringArrayP("env", "e", nil, "Flag to specify an environment variable [--env VARIABLE=value].") - cmd.Flags().StringArray("property-file", nil, "Add a property file to the integration.") - cmd.Flags().StringArrayP("property", "p", nil, "Add a Camel property to the integration.") - cmd.Flags().StringArray("maven-repository", nil, "Use a maven repository") + cmd.Flags().StringArray("property-file", nil, usagePropertyFile) + cmd.Flags().StringArrayP("property", "p", nil, usageProperty) return &cmd, &options } @@ -93,21 +92,21 @@ type localRunCmdOptions struct { EnvironmentVariables []string `mapstructure:"envs"` PropertyFiles []string `mapstructure:"property-files"` Properties []string `mapstructure:"properties"` - MavenRepositories []string `mapstructure:"maven-repositories"` } func (o *localRunCmdOptions) validate(args []string) error { - // Validate integration files when no image is provided and we are - // not running an already locally-built integration. - if o.Image == "" && o.IntegrationDirectory == "" { - if len(args) == 0 { - return errors.New("no integration files have been provided") - } + if len(args) == 0 && o.IntegrationDirectory == "" && o.Image == "" { + return errors.New("either integration files, --image, or --integration-directory must be provided") + } - // Validate integration files. - if err := validateFiles(args); err != nil { - return err - } + // If containerize is set then docker image name must be set. + if o.Containerize && o.Image == "" { + return errors.New("--containerize requires --image") + } + + // Validate integration files. + if err := validateFiles(args); err != nil { + return err } // Validate additional dependencies specified by the user. @@ -120,9 +119,12 @@ func (o *localRunCmdOptions) validate(args []string) error { return err } - // If containerize is set then docker image name must be set. - if o.Containerize && o.Image == "" { - return errors.New("containerization is active but no image name has been provided") + if o.IntegrationDirectory != "" { + if ok, err := util.DirectoryExists(o.IntegrationDirectory); err != nil { + return err + } else if !ok { + return errors.Errorf("integration directory %q does not exist", o.IntegrationDirectory) + } } return nil @@ -133,14 +135,11 @@ func (o *localRunCmdOptions) init() error { if err := createDockerBaseWorkingDirectory(); err != nil { return err } - if err := createDockerWorkingDirectory(); err != nil { return err } } - setDockerNetworkName(o.Network) - setDockerEnvVars(o.EnvironmentVariables) return createMavenWorkingDirectory() @@ -167,14 +166,13 @@ func (o *localRunCmdOptions) run(cmd *cobra.Command, args []string) error { } if o.Containerize { - // If this is a containerized local run, create, build and run the container image. + // Create, build, and run the container image. if err := createAndBuildIntegrationImage(o.Context, "", false, o.Image, propertyFiles, dependencies, routes, o.IntegrationDirectory != "", cmd.OutOrStdout(), cmd.ErrOrStderr()); err != nil { return err } - // Run integration image. return runIntegrationImage(o.Context, o.Image, cmd.OutOrStdout(), cmd.ErrOrStderr()) } diff --git a/pkg/cmd/local_util.go b/pkg/cmd/local_util.go index 166489a7a1..bc51bd6745 100644 --- a/pkg/cmd/local_util.go +++ b/pkg/cmd/local_util.go @@ -50,13 +50,13 @@ func getDependencies(ctx context.Context, args []string, additionalDependencies // Fetch existing catalog or create new one if one does not already exist catalog, err := createCamelCatalog(ctx) if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to create Camel catalog") } // Get top-level dependencies dependencies, err := getTopLevelDependencies(ctx, catalog, args) if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to get top-level dependencies") } // Add additional user-provided dependencies @@ -72,9 +72,10 @@ func getDependencies(ctx context.Context, args []string, additionalDependencies dependencies, err = getTransitiveDependencies(ctx, catalog, dependencies, repositories) if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to compute transitive dependencies") } } + return dependencies, nil } From 88cba264a0dd135f467744972f4421ad884142f3 Mon Sep 17 00:00:00 2001 From: Tadayoshi Sato Date: Fri, 29 Jul 2022 17:08:32 +0900 Subject: [PATCH 8/9] chore(cli): refactor - package utils to local & source for better encapsulation and cohesion --- .../container.go} | 28 +++---- pkg/cmd/{local_util.go => local/local.go} | 57 +++++++------- .../local_test.go} | 8 +- .../{local_util_dirs.go => local/workdir.go} | 40 +++++----- pkg/cmd/local_build.go | 37 ++++----- pkg/cmd/local_inspect.go | 13 ++-- pkg/cmd/local_run.go | 61 ++++++++------- pkg/cmd/modeline.go | 5 +- pkg/cmd/run.go | 12 +-- pkg/cmd/run_help.go | 9 ++- pkg/cmd/run_test.go | 5 +- .../{util_content.go => source/content.go} | 24 ++++-- .../content_test.go} | 26 +++---- pkg/cmd/{util_sources.go => source/source.go} | 78 +++++++++---------- pkg/cmd/source/util.go | 62 +++++++++++++++ pkg/cmd/{ => source}/util_test.go | 18 ++--- pkg/cmd/util.go | 45 ----------- 17 files changed, 282 insertions(+), 246 deletions(-) rename pkg/cmd/{local_util_container.go => local/container.go} (93%) rename pkg/cmd/{local_util.go => local/local.go} (89%) rename pkg/cmd/{local_util_test.go => local/local_test.go} (93%) rename pkg/cmd/{local_util_dirs.go => local/workdir.go} (85%) rename pkg/cmd/{util_content.go => source/content.go} (85%) rename pkg/cmd/{util_content_test.go => source/content_test.go} (83%) rename pkg/cmd/{util_sources.go => source/source.go} (77%) create mode 100644 pkg/cmd/source/util.go rename pkg/cmd/{ => source}/util_test.go (76%) diff --git a/pkg/cmd/local_util_container.go b/pkg/cmd/local/container.go similarity index 93% rename from pkg/cmd/local_util_container.go rename to pkg/cmd/local/container.go index 109ca030da..8174176d84 100644 --- a/pkg/cmd/local_util_container.go +++ b/pkg/cmd/local/container.go @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package local import ( "context" @@ -35,8 +35,8 @@ import ( // Local Docker file system management functions. -// createDockerBaseWorkingDirectory creates local docker base directory. -func createDockerBaseWorkingDirectory() error { +// CreateDockerBaseWorkingDirectory creates local docker base directory. +func CreateDockerBaseWorkingDirectory() error { temporaryDirectory, err := ioutil.TempDir(os.TempDir(), "docker-base-") if err != nil { return err @@ -48,13 +48,13 @@ func createDockerBaseWorkingDirectory() error { return nil } -// deleteDockerBaseWorkingDirectory removes directory used for computing the base dependencies. -func deleteDockerBaseWorkingDirectory() error { +// DeleteDockerBaseWorkingDirectory removes directory used for computing the base dependencies. +func DeleteDockerBaseWorkingDirectory() error { return os.RemoveAll(docker.BaseWorkingDirectory) } -// createDockerWorkingDirectory creates local docker directory. -func createDockerWorkingDirectory() error { +// CreateDockerWorkingDirectory creates local docker directory. +func CreateDockerWorkingDirectory() error { temporaryDirectory, err := ioutil.TempDir(os.TempDir(), "docker-") if err != nil { return err @@ -66,18 +66,18 @@ func createDockerWorkingDirectory() error { return nil } -// deleteDockerWorkingDirectory removes directory used for computing the integration dependencies. -func deleteDockerWorkingDirectory() error { +// DeleteDockerWorkingDirectory removes directory used for computing the integration dependencies. +func DeleteDockerWorkingDirectory() error { return os.RemoveAll(docker.IntegrationWorkingDirectory) } -func setDockerNetworkName(networkName string) { +func SetDockerNetworkName(networkName string) { if networkName != "" { docker.NetworkName = networkName } } -func setDockerEnvVars(envVars []string) { +func SetDockerEnvVars(envVars []string) { if len(envVars) > 0 { util.CLIEnvVars = envVars } @@ -132,7 +132,7 @@ func setupDockerRegistry(containerRegistry string, image string, justBaseImage b return nil } -func createAndBuildIntegrationImage(ctx context.Context, containerRegistry string, justBaseImage bool, image string, +func CreateAndBuildIntegrationImage(ctx context.Context, containerRegistry string, justBaseImage bool, image string, propertyFiles []string, dependencies []string, routes []string, startsFromLocalFolder bool, stdout, stderr io.Writer) error { if err := setupDockerRegistry(containerRegistry, image, justBaseImage); err != nil { @@ -213,7 +213,7 @@ func buildIntegrationImage(ctx context.Context, image string, stdout, stderr io. return nil } -func runIntegrationImage(ctx context.Context, image string, stdout, stderr io.Writer) error { +func RunIntegrationImage(ctx context.Context, image string, stdout, stderr io.Writer) error { // Stop the child process before exiting dockerCtx, cancel := context.WithCancel(ctx) cs := make(chan os.Signal, 1) @@ -259,7 +259,7 @@ func getContainerIntegrationRunCommand(ctx context.Context, properties []string, docker.GetContainerPropertiesDir(), stdout, stderr, false) } -func runLocalIntegration(ctx context.Context, properties []string, dependencies []string, routes []string, +func RunLocalIntegration(ctx context.Context, properties []string, dependencies []string, routes []string, propertiesDir string, stdout, stderr io.Writer) error { cmd, err := assembleIntegrationRunCommand(ctx, properties, dependencies, routes, propertiesDir, stdout, stderr, true) diff --git a/pkg/cmd/local_util.go b/pkg/cmd/local/local.go similarity index 89% rename from pkg/cmd/local_util.go rename to pkg/cmd/local/local.go index bc51bd6745..8f150ad6cd 100644 --- a/pkg/cmd/local_util.go +++ b/pkg/cmd/local/local.go @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package local import ( "context" @@ -32,6 +32,7 @@ import ( v1 "github.com/apache/camel-k/pkg/apis/camel/v1" "github.com/apache/camel-k/pkg/builder" + "github.com/apache/camel-k/pkg/cmd/source" "github.com/apache/camel-k/pkg/trait" "github.com/apache/camel-k/pkg/util" "github.com/apache/camel-k/pkg/util/camel" @@ -45,8 +46,8 @@ var acceptedDependencyTypes = []string{ "github", "gitlab", "bitbucket", "gitee", "azure", } -// getDependencies resolves and gets the list of dependencies from catalog and sources. -func getDependencies(ctx context.Context, args []string, additionalDependencies []string, repositories []string, allDependencies bool) ([]string, error) { +// GetDependencies resolves and gets the list of dependencies from catalog and sources. +func GetDependencies(ctx context.Context, args []string, additionalDependencies []string, repositories []string, allDependencies bool) ([]string, error) { // Fetch existing catalog or create new one if one does not already exist catalog, err := createCamelCatalog(ctx) if err != nil { @@ -84,15 +85,15 @@ func getTopLevelDependencies(ctx context.Context, catalog *camel.RuntimeCatalog, dependencies := strset.New() // Invoke the dependency inspector code for each source file - for _, source := range args { - data, _, _, err := loadTextContent(ctx, source, false) + for _, src := range args { + data, _, _, err := source.LoadTextContent(ctx, src, false) if err != nil { return []string{}, err } sourceSpec := v1.SourceSpec{ DataSpec: v1.DataSpec{ - Name: path.Base(source), + Name: path.Base(src), Content: data, Compression: false, }, @@ -175,24 +176,24 @@ func getRegularFilesInDir(directory string, dirnameInPath bool) ([]string, error return dirFiles, nil } -func getLocalBuildDependencies(integrationDirectory string) ([]string, error) { - locallyBuiltDependencies, err := getRegularFilesInDir(getCustomDependenciesDir(integrationDirectory), true) +func GetBuildDependencies(integrationDirectory string) ([]string, error) { + locallyBuiltDependencies, err := getRegularFilesInDir(GetCustomDependenciesDir(integrationDirectory), true) if err != nil { return nil, err } return locallyBuiltDependencies, nil } -func getLocalBuildProperties(integrationDirectory string) ([]string, error) { - locallyBuiltProperties, err := getRegularFilesInDir(getCustomPropertiesDir(integrationDirectory), true) +func GetBuildProperties(integrationDirectory string) ([]string, error) { + locallyBuiltProperties, err := getRegularFilesInDir(GetCustomPropertiesDir(integrationDirectory), true) if err != nil { return nil, err } return locallyBuiltProperties, nil } -func getLocalBuildRoutes(integrationDirectory string) ([]string, error) { - locallyBuiltRoutes, err := getRegularFilesInDir(getCustomRoutesDir(integrationDirectory), true) +func GetBuildRoutes(integrationDirectory string) ([]string, error) { + locallyBuiltRoutes, err := getRegularFilesInDir(GetCustomRoutesDir(integrationDirectory), true) if err != nil { return nil, err } @@ -236,7 +237,7 @@ func createCamelCatalog(ctx context.Context) (*camel.RuntimeCatalog, error) { return catalog, nil } -func outputDependencies(dependencies []string, format string, cmd *cobra.Command) error { +func OutputDependencies(dependencies []string, format string, cmd *cobra.Command) error { if format != "" { if err := printDependencies(format, dependencies, cmd); err != nil { return err @@ -300,8 +301,8 @@ func validateFile(file string) error { return nil } -// validateFiles ensures existence of given files. -func validateFiles(args []string) error { +// ValidateFiles ensures existence of given files. +func ValidateFiles(args []string) error { // Ensure source files exist for _, arg := range args { err := validateFile(arg) @@ -313,9 +314,9 @@ func validateFiles(args []string) error { return nil } -// validateDependencies validates list of additional dependencies i.e. makes sure +// ValidateDependencies validates list of additional dependencies i.e. makes sure // that each dependency has a valid type. -func validateDependencies(dependencies []string) error { +func ValidateDependencies(dependencies []string) error { for _, dependency := range dependencies { depType := strings.Split(dependency, ":")[0] if !util.StringSliceExists(acceptedDependencyTypes, depType) { @@ -326,7 +327,7 @@ func validateDependencies(dependencies []string) error { return nil } -func validatePropertyFiles(propertyFiles []string) error { +func ValidatePropertyFiles(propertyFiles []string) error { for _, fileName := range propertyFiles { if err := validatePropertyFile(fileName); err != nil { return err @@ -350,16 +351,16 @@ func validatePropertyFile(fileName string) error { return nil } -func updateIntegrationProperties(properties []string, propertyFiles []string, hasIntegrationDir bool) ([]string, error) { +func UpdateIntegrationProperties(properties []string, propertyFiles []string, hasIntegrationDir bool) ([]string, error) { // Create properties directory under Maven working directory. // This ensures that property files of different integrations do not clash. - if err := createLocalPropertiesDirectory(); err != nil { + if err := CreateLocalPropertiesDirectory(); err != nil { return nil, err } // Relocate properties files to this integration's property directory. relocatedPropertyFiles := []string{} - dir := getLocalPropertiesDir() + dir := GetLocalPropertiesDir() for _, propertyFile := range propertyFiles { relocatedPropertyFile := path.Join(dir, path.Base(propertyFile)) if _, err := util.CopyFile(propertyFile, relocatedPropertyFile); err != nil { @@ -428,7 +429,7 @@ func updateQuarkusDirectory() error { } // ignore error if custom dir doesn't exist - _ = copyQuarkusAppFiles(util.CustomQuarkusDirectoryName, getLocalQuarkusDir()) + _ = CopyQuarkusAppFiles(util.CustomQuarkusDirectoryName, getLocalQuarkusDir()) return nil } @@ -439,7 +440,7 @@ func updateAppDirectory() error { } // ignore error if custom dir doesn't exist - _ = copyAppFile(util.CustomAppDirectoryName, getLocalAppDir()) + _ = CopyAppFile(util.CustomAppDirectoryName, getLocalAppDir()) return nil } @@ -450,12 +451,12 @@ func updateLibDirectory() error { } // ignore error if custom dir doesn't exist - _ = copyLibFiles(util.CustomLibDirectoryName, getLocalLibDir()) + _ = CopyLibFiles(util.CustomLibDirectoryName, getLocalLibDir()) return nil } -func copyIntegrationFilesToDirectory(files []string, directory string) ([]string, error) { +func CopyIntegrationFilesToDirectory(files []string, directory string) ([]string, error) { // Create directory if one does not already exist if err := util.CreateDirectory(directory); err != nil { return nil, err @@ -474,7 +475,7 @@ func copyIntegrationFilesToDirectory(files []string, directory string) ([]string return relocatedFilesList, nil } -func copyQuarkusAppFiles(dependenciesDir string, quarkusDir string) error { +func CopyQuarkusAppFiles(dependenciesDir string, quarkusDir string) error { // Create directory if one does not already exist if err := util.CreateDirectory(quarkusDir); err != nil { return err @@ -498,7 +499,7 @@ func copyQuarkusAppFiles(dependenciesDir string, quarkusDir string) error { return nil } -func copyLibFiles(dependenciesDir string, libDir string) error { +func CopyLibFiles(dependenciesDir string, libDir string) error { // Create directory if one does not already exist if err := util.CreateDirectory(libDir); err != nil { return err @@ -520,7 +521,7 @@ func copyLibFiles(dependenciesDir string, libDir string) error { return nil } -func copyAppFile(dependenciesDir string, appDir string) error { +func CopyAppFile(dependenciesDir string, appDir string) error { // Create directory if one does not already exist if err := util.CreateDirectory(appDir); err != nil { return err diff --git a/pkg/cmd/local_util_test.go b/pkg/cmd/local/local_test.go similarity index 93% rename from pkg/cmd/local_util_test.go rename to pkg/cmd/local/local_test.go index 2f44490aab..2079472415 100644 --- a/pkg/cmd/local_util_test.go +++ b/pkg/cmd/local/local_test.go @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package local import ( "io/ioutil" @@ -37,7 +37,7 @@ func TestValidatePropertyFiles_ShouldSucceed(t *testing.T) { assert.Nil(t, ioutil.WriteFile(tmpFile1.Name(), []byte("key=value"), 0o400)) inputValues := []string{tmpFile1.Name()} - err = validatePropertyFiles(inputValues) + err = ValidatePropertyFiles(inputValues) assert.Nil(t, err) } @@ -53,7 +53,7 @@ func TestValidatePropertyFiles_ShouldFailNotAPropertiesFile(t *testing.T) { assert.Nil(t, ioutil.WriteFile(tmpFile1.Name(), []byte("key=value"), 0o400)) inputValues := []string{tmpFile1.Name()} - err = validatePropertyFiles(inputValues) + err = ValidatePropertyFiles(inputValues) assert.NotNil(t, err) assert.True(t, strings.HasPrefix(err.Error(), "supported property files must have a .properties extension")) @@ -61,7 +61,7 @@ func TestValidatePropertyFiles_ShouldFailNotAPropertiesFile(t *testing.T) { func TestValidatePropertyFiles_ShouldFailNotFound(t *testing.T) { inputValues := []string{"/tmp/not-found.properties"} - err := validatePropertyFiles(inputValues) + err := ValidatePropertyFiles(inputValues) assert.NotNil(t, err) assert.True(t, strings.HasPrefix(err.Error(), "unable to access property file")) diff --git a/pkg/cmd/local_util_dirs.go b/pkg/cmd/local/workdir.go similarity index 85% rename from pkg/cmd/local_util_dirs.go rename to pkg/cmd/local/workdir.go index 7d0311d121..3ab67f5ba5 100644 --- a/pkg/cmd/local_util_dirs.go +++ b/pkg/cmd/local/workdir.go @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package local import ( "io/ioutil" @@ -30,8 +30,8 @@ import ( // By default, a temporary folder will be used. var MavenWorkingDirectory = "" -// createMavenWorkingDirectory creates local Maven working directory. -func createMavenWorkingDirectory() error { +// CreateMavenWorkingDirectory creates local Maven working directory. +func CreateMavenWorkingDirectory() error { temporaryDirectory, err := ioutil.TempDir(os.TempDir(), "maven-") if err != nil { return err @@ -43,8 +43,8 @@ func createMavenWorkingDirectory() error { return nil } -// deleteMavenWorkingDirectory removes local Maven working directory. -func deleteMavenWorkingDirectory() error { +// DeleteMavenWorkingDirectory removes local Maven working directory. +func DeleteMavenWorkingDirectory() error { return os.RemoveAll(MavenWorkingDirectory) } @@ -73,24 +73,24 @@ func createLocalDependenciesDirectory() error { return nil } -// getLocalPropertiesDir returns /properties. -func getLocalPropertiesDir() string { +// GetLocalPropertiesDir returns /properties. +func GetLocalPropertiesDir() string { return path.Join(MavenWorkingDirectory, util.DefaultPropertiesDirectoryName) } -func createLocalPropertiesDirectory() error { +func CreateLocalPropertiesDirectory() error { // Do not create a directory unless the maven directory contains a valid value. if MavenWorkingDirectory == "" { return nil } - directoryExists, err := util.DirectoryExists(getLocalPropertiesDir()) + directoryExists, err := util.DirectoryExists(GetLocalPropertiesDir()) if err != nil { return err } if !directoryExists { - err := os.MkdirAll(getLocalPropertiesDir(), 0o700) + err := os.MkdirAll(GetLocalPropertiesDir(), 0o700) if err != nil { return err } @@ -199,38 +199,38 @@ func createLocalLibDirectory() error { return nil } -func getCustomDependenciesDir(dir string) string { +func GetCustomDependenciesDir(dir string) string { return path.Join(dir, util.DefaultDependenciesDirectoryName) } -func getCustomPropertiesDir(dir string) string { +func GetCustomPropertiesDir(dir string) string { return path.Join(dir, util.DefaultPropertiesDirectoryName) } -func getCustomRoutesDir(dir string) string { +func GetCustomRoutesDir(dir string) string { return path.Join(dir, util.DefaultRoutesDirectoryName) } -func getCustomQuarkusDir(dir string) string { +func GetCustomQuarkusDir(dir string) string { parentDir := path.Dir(strings.TrimSuffix(dir, "/")) return path.Join(parentDir, util.CustomQuarkusDirectoryName) } -func getCustomLibDir(dir string) string { +func GetCustomLibDir(dir string) string { parentDir := path.Dir(strings.TrimSuffix(dir, "/")) return path.Join(parentDir, util.CustomLibDirectoryName) } -func getCustomAppDir(dir string) string { +func GetCustomAppDir(dir string) string { parentDir := path.Dir(strings.TrimSuffix(dir, "/")) return path.Join(parentDir, "app") } -func deleteLocalIntegrationDirs(dir string) error { +func DeleteLocalIntegrationDirs(dir string) error { dirs := []string{ - getCustomQuarkusDir(dir), - getCustomLibDir(dir), - getCustomAppDir(dir), + GetCustomQuarkusDir(dir), + GetCustomLibDir(dir), + GetCustomAppDir(dir), } for _, dir := range dirs { diff --git a/pkg/cmd/local_build.go b/pkg/cmd/local_build.go index cf36c9d858..6f8cbcfd03 100644 --- a/pkg/cmd/local_build.go +++ b/pkg/cmd/local_build.go @@ -23,6 +23,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" + "github.com/apache/camel-k/pkg/cmd/local" "github.com/apache/camel-k/pkg/util" ) @@ -139,17 +140,17 @@ func (o *localBuildCmdOptions) validateIntegrationMode(args []string) error { } // Validate integration files. - if err := validateFiles(args); err != nil { + if err := local.ValidateFiles(args); err != nil { return err } // Validate additional dependencies specified by the user. - if err := validateDependencies(o.Dependencies); err != nil { + if err := local.ValidateDependencies(o.Dependencies); err != nil { return err } // Validate properties file. - if err := validateFiles(o.PropertyFiles); err != nil { + if err := local.ValidateFiles(o.PropertyFiles); err != nil { return err } @@ -166,19 +167,19 @@ func (o *localBuildCmdOptions) init(args []string) error { if o.BaseImage || o.Image != "" { // If base image construction is enabled create a directory for it. - if err := createDockerBaseWorkingDirectory(); err != nil { + if err := local.CreateDockerBaseWorkingDirectory(); err != nil { return err } // If integration image construction is enabled, an integration image will be built. if o.Image != "" { - if err := createDockerWorkingDirectory(); err != nil { + if err := local.CreateDockerWorkingDirectory(); err != nil { return err } } } - return createMavenWorkingDirectory() + return local.CreateMavenWorkingDirectory() } func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { @@ -186,7 +187,7 @@ func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { routeFiles := args if !o.BaseImage { - dependencies, err := getDependencies(o.Context, args, o.Dependencies, o.MavenRepositories, true) + dependencies, err := local.GetDependencies(o.Context, args, o.Dependencies, o.MavenRepositories, true) if err != nil { return err } @@ -194,7 +195,7 @@ func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { var propertyFiles []string if !o.DependenciesOnly { // Manage integration properties which may come from files or CLI - propertyFiles, err = updateIntegrationProperties(o.Properties, o.PropertyFiles, false) + propertyFiles, err = local.UpdateIntegrationProperties(o.Properties, o.PropertyFiles, false) if err != nil { return err } @@ -207,8 +208,8 @@ func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { // build the integration without also building the image. A local build of the integration is // represented by all the files that define the integration: dependencies, properties, and routes. if o.IntegrationDirectory != "" { - localDependenciesDir := getCustomDependenciesDir(o.IntegrationDirectory) - dependenciesList, err = copyIntegrationFilesToDirectory(dependencies, localDependenciesDir) + localDependenciesDir := local.GetCustomDependenciesDir(o.IntegrationDirectory) + dependenciesList, err = local.CopyIntegrationFilesToDirectory(dependencies, localDependenciesDir) if err != nil { return err } @@ -218,14 +219,14 @@ func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { return nil } - localPropertiesDir := getCustomPropertiesDir(o.IntegrationDirectory) - propertyFilesList, err = copyIntegrationFilesToDirectory(propertyFiles, localPropertiesDir) + localPropertiesDir := local.GetCustomPropertiesDir(o.IntegrationDirectory) + propertyFilesList, err = local.CopyIntegrationFilesToDirectory(propertyFiles, localPropertiesDir) if err != nil { return err } - localRoutesDir := getCustomRoutesDir(o.IntegrationDirectory) - routeFiles, err = copyIntegrationFilesToDirectory(args, localRoutesDir) + localRoutesDir := local.GetCustomRoutesDir(o.IntegrationDirectory) + routeFiles, err = local.CopyIntegrationFilesToDirectory(args, localRoutesDir) if err != nil { return err } @@ -240,7 +241,7 @@ func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { } } - if err := createAndBuildIntegrationImage(o.Context, o.ContainerRegistry, o.BaseImage, o.Image, + if err := local.CreateAndBuildIntegrationImage(o.Context, o.ContainerRegistry, o.BaseImage, o.Image, propertyFilesList, dependenciesList, routeFiles, false, cmd.OutOrStdout(), cmd.ErrOrStderr()); err != nil { return err @@ -251,16 +252,16 @@ func (o *localBuildCmdOptions) run(cmd *cobra.Command, args []string) error { func (o *localBuildCmdOptions) deinit() error { // If base image construction is enabled delete the directory for it. - if err := deleteDockerBaseWorkingDirectory(); err != nil { + if err := local.DeleteDockerBaseWorkingDirectory(); err != nil { return err } // If integration files are provided delete the maven project folder. if !o.BaseImage { - if err := deleteDockerWorkingDirectory(); err != nil { + if err := local.DeleteDockerWorkingDirectory(); err != nil { return err } - if err := deleteMavenWorkingDirectory(); err != nil { + if err := local.DeleteMavenWorkingDirectory(); err != nil { return err } } diff --git a/pkg/cmd/local_inspect.go b/pkg/cmd/local_inspect.go index 22c6aefb91..553f36fcaa 100644 --- a/pkg/cmd/local_inspect.go +++ b/pkg/cmd/local_inspect.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" + "github.com/apache/camel-k/pkg/cmd/local" "github.com/spf13/cobra" ) @@ -75,11 +76,11 @@ func (o *localInspectCmdOptions) validate(args []string) error { return errors.New("no integration files have been provided") } - if err := validateFiles(args); err != nil { + if err := local.ValidateFiles(args); err != nil { return err } - if err := validateDependencies(o.Dependencies); err != nil { + if err := local.ValidateDependencies(o.Dependencies); err != nil { return err } @@ -87,16 +88,16 @@ func (o *localInspectCmdOptions) validate(args []string) error { } func (o *localInspectCmdOptions) init() error { - return createMavenWorkingDirectory() + return local.CreateMavenWorkingDirectory() } func (o *localInspectCmdOptions) run(cmd *cobra.Command, args []string) error { - dependencies, err := getDependencies(o.Context, args, o.Dependencies, o.MavenRepositories, o.AllDependencies) + dependencies, err := local.GetDependencies(o.Context, args, o.Dependencies, o.MavenRepositories, o.AllDependencies) if err != nil { return err } - if err = outputDependencies(dependencies, o.OutputFormat, cmd); err != nil { + if err = local.OutputDependencies(dependencies, o.OutputFormat, cmd); err != nil { return err } @@ -104,5 +105,5 @@ func (o *localInspectCmdOptions) run(cmd *cobra.Command, args []string) error { } func (o *localInspectCmdOptions) deinit() error { - return deleteMavenWorkingDirectory() + return local.DeleteMavenWorkingDirectory() } diff --git a/pkg/cmd/local_run.go b/pkg/cmd/local_run.go index 467c35076d..2c3ce54a7d 100644 --- a/pkg/cmd/local_run.go +++ b/pkg/cmd/local_run.go @@ -23,6 +23,7 @@ import ( "os/signal" "syscall" + "github.com/apache/camel-k/pkg/cmd/local" "github.com/apache/camel-k/pkg/util" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -105,17 +106,17 @@ func (o *localRunCmdOptions) validate(args []string) error { } // Validate integration files. - if err := validateFiles(args); err != nil { + if err := local.ValidateFiles(args); err != nil { return err } // Validate additional dependencies specified by the user. - if err := validateDependencies(o.Dependencies); err != nil { + if err := local.ValidateDependencies(o.Dependencies); err != nil { return err } // Validate properties file. - if err := validatePropertyFiles(o.PropertyFiles); err != nil { + if err := local.ValidatePropertyFiles(o.PropertyFiles); err != nil { return err } @@ -132,24 +133,24 @@ func (o *localRunCmdOptions) validate(args []string) error { func (o *localRunCmdOptions) init() error { if o.Containerize { - if err := createDockerBaseWorkingDirectory(); err != nil { + if err := local.CreateDockerBaseWorkingDirectory(); err != nil { return err } - if err := createDockerWorkingDirectory(); err != nil { + if err := local.CreateDockerWorkingDirectory(); err != nil { return err } } - setDockerNetworkName(o.Network) - setDockerEnvVars(o.EnvironmentVariables) + local.SetDockerNetworkName(o.Network) + local.SetDockerEnvVars(o.EnvironmentVariables) - return createMavenWorkingDirectory() + return local.CreateMavenWorkingDirectory() } func (o *localRunCmdOptions) run(cmd *cobra.Command, args []string) error { // If local run is provided with an image name, it will just run the image locally and exit. if o.Image != "" && !o.Containerize { // Run image locally. - return runIntegrationImage(o.Context, o.Image, cmd.OutOrStdout(), cmd.ErrOrStderr()) + return local.RunIntegrationImage(o.Context, o.Image, cmd.OutOrStdout(), cmd.ErrOrStderr()) } dependencies, err := o.processDependencies(args) @@ -167,29 +168,29 @@ func (o *localRunCmdOptions) run(cmd *cobra.Command, args []string) error { if o.Containerize { // Create, build, and run the container image. - if err := createAndBuildIntegrationImage(o.Context, "", false, o.Image, + if err := local.CreateAndBuildIntegrationImage(o.Context, "", false, o.Image, propertyFiles, dependencies, routes, o.IntegrationDirectory != "", cmd.OutOrStdout(), cmd.ErrOrStderr()); err != nil { return err } - return runIntegrationImage(o.Context, o.Image, cmd.OutOrStdout(), cmd.ErrOrStderr()) + return local.RunIntegrationImage(o.Context, o.Image, cmd.OutOrStdout(), cmd.ErrOrStderr()) } // Run integration locally. - return runLocalIntegration(o.Context, propertyFiles, dependencies, routes, o.getPropertiesDir(), + return local.RunLocalIntegration(o.Context, propertyFiles, dependencies, routes, o.getPropertiesDir(), cmd.OutOrStdout(), cmd.ErrOrStderr()) } func (o *localRunCmdOptions) processDependencies(args []string) ([]string, error) { if o.IntegrationDirectory == "" { - return getDependencies(o.Context, args, o.Dependencies, o.MavenRepositories, true) + return local.GetDependencies(o.Context, args, o.Dependencies, o.MavenRepositories, true) } // Set up on the integration directory // Fetch local dependencies - dependencies, err := getLocalBuildDependencies(o.IntegrationDirectory) + dependencies, err := local.GetBuildDependencies(o.IntegrationDirectory) if err != nil { return nil, err } @@ -203,27 +204,27 @@ func (o *localRunCmdOptions) processDependencies(args []string) ([]string, error // setupDependenciesForQuarkusRun sets up resources under the integration directory for running Quarkus app. func (o *localRunCmdOptions) setupDependenciesForQuarkusRun() error { // Local dependencies directory - localDependenciesDir := getCustomDependenciesDir(o.IntegrationDirectory) + localDependenciesDir := local.GetCustomDependenciesDir(o.IntegrationDirectory) // The quarkus application files need to be at a specific location i.e.: // /../quarkus/quarkus-application.dat // /../quarkus/generated-bytecode.jar - localQuarkusDir := getCustomQuarkusDir(o.IntegrationDirectory) - if err := copyQuarkusAppFiles(localDependenciesDir, localQuarkusDir); err != nil { + localQuarkusDir := local.GetCustomQuarkusDir(o.IntegrationDirectory) + if err := local.CopyQuarkusAppFiles(localDependenciesDir, localQuarkusDir); err != nil { return err } // The dependency jar files need to be at a specific location i.e.: // /../lib/main/*.jar - localLibDir := getCustomLibDir(o.IntegrationDirectory) - if err := copyLibFiles(localDependenciesDir, localLibDir); err != nil { + localLibDir := local.GetCustomLibDir(o.IntegrationDirectory) + if err := local.CopyLibFiles(localDependenciesDir, localLibDir); err != nil { return err } // The Camel K jar file needs to be at a specific location i.e.: // /../app/camel-k-integration-X.X.X{-SNAPSHOT}.jar - localAppDir := getCustomAppDir(o.IntegrationDirectory) - if err := copyAppFile(localDependenciesDir, localAppDir); err != nil { + localAppDir := local.GetCustomAppDir(o.IntegrationDirectory) + if err := local.CopyAppFile(localDependenciesDir, localAppDir); err != nil { return err } @@ -235,14 +236,14 @@ func (o *localRunCmdOptions) processPropertyFiles() ([]string, error) { propertyFiles := o.PropertyFiles hasIntegrationDir := o.IntegrationDirectory != "" if hasIntegrationDir { - localPropertyFiles, err := getLocalBuildProperties(o.IntegrationDirectory) + localPropertyFiles, err := local.GetBuildProperties(o.IntegrationDirectory) if err != nil { return nil, err } propertyFiles = localPropertyFiles } - return updateIntegrationProperties(o.Properties, propertyFiles, hasIntegrationDir) + return local.UpdateIntegrationProperties(o.Properties, propertyFiles, hasIntegrationDir) } func (o *localRunCmdOptions) processRoutes(args []string) ([]string, error) { @@ -250,33 +251,33 @@ func (o *localRunCmdOptions) processRoutes(args []string) ([]string, error) { return args, nil } - return getLocalBuildRoutes(o.IntegrationDirectory) + return local.GetBuildRoutes(o.IntegrationDirectory) } func (o *localRunCmdOptions) getPropertiesDir() string { if o.IntegrationDirectory == "" { - return getLocalPropertiesDir() + return local.GetLocalPropertiesDir() } - return getCustomPropertiesDir(o.IntegrationDirectory) + return local.GetCustomPropertiesDir(o.IntegrationDirectory) } func (o *localRunCmdOptions) deinit() error { if o.Containerize { - if err := deleteDockerBaseWorkingDirectory(); err != nil { + if err := local.DeleteDockerBaseWorkingDirectory(); err != nil { return err } - if err := deleteDockerWorkingDirectory(); err != nil { + if err := local.DeleteDockerWorkingDirectory(); err != nil { return err } } if o.IntegrationDirectory != "" { - if err := deleteLocalIntegrationDirs(o.IntegrationDirectory); err != nil { + if err := local.DeleteLocalIntegrationDirs(o.IntegrationDirectory); err != nil { return err } } - return deleteMavenWorkingDirectory() + return local.DeleteMavenWorkingDirectory() } diff --git a/pkg/cmd/modeline.go b/pkg/cmd/modeline.go index 07e88155bb..4ef02caa22 100644 --- a/pkg/cmd/modeline.go +++ b/pkg/cmd/modeline.go @@ -24,6 +24,7 @@ import ( "path/filepath" "strings" + "github.com/apache/camel-k/pkg/cmd/source" "github.com/apache/camel-k/pkg/util" "github.com/apache/camel-k/pkg/util/modeline" "github.com/pkg/errors" @@ -194,7 +195,7 @@ func createKamelWithModelineCommand(ctx context.Context, args []string) (*cobra. func extractModelineOptions(ctx context.Context, sources []string, cmd *cobra.Command) ([]modeline.Option, error) { opts := make([]modeline.Option, 0) - resolvedSources, err := ResolveSources(ctx, sources, false, cmd) + resolvedSources, err := source.Resolve(ctx, sources, false, cmd) if err != nil { return opts, errors.Wrap(err, "failed to resolve sources") } @@ -216,7 +217,7 @@ func extractModelineOptions(ctx context.Context, sources []string, cmd *cobra.Co return opts, nil } -func extractModelineOptionsFromSource(resolvedSource Source) ([]modeline.Option, error) { +func extractModelineOptionsFromSource(resolvedSource source.Source) ([]modeline.Option, error) { ops, err := modeline.Parse(resolvedSource.Name, resolvedSource.Content) if err != nil { return ops, errors.Wrapf(err, "cannot process file %s", resolvedSource.Location) diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go index e84a628e6b..a3282e1f7a 100644 --- a/pkg/cmd/run.go +++ b/pkg/cmd/run.go @@ -61,6 +61,8 @@ import ( v1 "github.com/apache/camel-k/pkg/apis/camel/v1" "github.com/apache/camel-k/pkg/client" + "github.com/apache/camel-k/pkg/cmd/local" + "github.com/apache/camel-k/pkg/cmd/source" platformutil "github.com/apache/camel-k/pkg/platform" "github.com/apache/camel-k/pkg/trait" "github.com/apache/camel-k/pkg/util" @@ -238,7 +240,7 @@ func (o *runCmdOptions) validateArgs(cmd *cobra.Command, args []string) error { return errors.New("run expects at least 1 argument, received 0") } - if _, err := ResolveSources(context.Background(), args, false, cmd); err != nil { + if _, err := source.Resolve(context.Background(), args, false, cmd); err != nil { return errors.Wrap(err, "One of the provided sources is not reachable") } @@ -259,7 +261,7 @@ func (o *runCmdOptions) validate() error { propertyFiles := filterBuildPropertyFiles(o.Properties) propertyFiles = append(propertyFiles, filterBuildPropertyFiles(o.BuildProperties)...) - err := validatePropertyFiles(propertyFiles) + err := local.ValidatePropertyFiles(propertyFiles) if err != nil { return err } @@ -441,7 +443,7 @@ func (o *runCmdOptions) syncIntegration(cmd *cobra.Command, c client.Client, sou files = append(files, filterFileLocation(o.OpenAPIs)...) for _, s := range files { - ok, err := isLocalAndFileExists(s) + ok, err := source.IsLocalAndFileExists(s) if err != nil { return err } @@ -578,7 +580,7 @@ func (o *runCmdOptions) createOrUpdateIntegration(cmd *cobra.Command, c client.C srcs = append(srcs, sources...) srcs = append(srcs, o.Sources...) - resolvedSources, err := ResolveSources(context.Background(), srcs, o.Compression, cmd) + resolvedSources, err := source.Resolve(context.Background(), srcs, o.Compression, cmd) if err != nil { return nil, err } @@ -801,7 +803,7 @@ func resolvePodTemplate(ctx context.Context, cmd *cobra.Command, templateSrc str // check if value is a path to the file if _, err := os.Stat(templateSrc); err == nil { - rsc, err := ResolveSources(ctx, []string{templateSrc}, false, cmd) + rsc, err := source.Resolve(ctx, []string{templateSrc}, false, cmd) if err == nil && len(rsc) > 0 { templateSrc = rsc[0].Content } diff --git a/pkg/cmd/run_help.go b/pkg/cmd/run_help.go index 1f868292df..c885e4151c 100644 --- a/pkg/cmd/run_help.go +++ b/pkg/cmd/run_help.go @@ -25,6 +25,7 @@ import ( v1 "github.com/apache/camel-k/pkg/apis/camel/v1" "github.com/apache/camel-k/pkg/client" + "github.com/apache/camel-k/pkg/cmd/source" "github.com/apache/camel-k/pkg/util/kubernetes" "github.com/apache/camel-k/pkg/util/resource" "github.com/magiconair/properties" @@ -48,11 +49,11 @@ func parseConfigAndGenCm(ctx context.Context, cmd *cobra.Command, c client.Clien } case resource.StorageTypeFile: // Don't allow a binary non compressed resource - rawData, contentType, err := loadRawContent(ctx, config.Name()) + rawData, contentType, err := source.LoadRawContent(ctx, config.Name()) if err != nil { return nil, err } - if config.ContentType() != resource.ContentTypeData && !enableCompression && isBinary(contentType) { + if config.ContentType() != resource.ContentTypeData && !enableCompression && source.IsBinary(contentType) { return nil, fmt.Errorf("you cannot provide a binary config, use a text file or check --resource flag instead") } resourceType := v1.ResourceTypeData @@ -85,13 +86,13 @@ func binaryOrTextResource(fileName string, data []byte, contentType string, base Type: resourceType, } - if !base64Compression && isBinary(contentType) { + if !base64Compression && source.IsBinary(contentType) { resourceSpec.RawContent = data return resourceSpec, nil } // either is a text resource or base64 compression is enabled if base64Compression { - content, err := compressToString(data) + content, err := source.CompressToString(data) if err != nil { return resourceSpec, err } diff --git a/pkg/cmd/run_test.go b/pkg/cmd/run_test.go index d535164002..b02f37698c 100644 --- a/pkg/cmd/run_test.go +++ b/pkg/cmd/run_test.go @@ -27,6 +27,7 @@ import ( v1 "github.com/apache/camel-k/pkg/apis/camel/v1" traitv1 "github.com/apache/camel-k/pkg/apis/camel/v1/trait" + "github.com/apache/camel-k/pkg/cmd/source" "github.com/apache/camel-k/pkg/platform" "github.com/apache/camel-k/pkg/trait" "github.com/apache/camel-k/pkg/util/test" @@ -463,7 +464,7 @@ func TestRunBinaryResource(t *testing.T) { func TestRunBinaryCompressedResource(t *testing.T) { data := []byte{1, 2, 3, 4} - base64Compressed, _ := compressToString(data) + base64Compressed, _ := source.CompressToString(data) binaryResourceSpec, err := binaryOrTextResource("file.ext", data, "application/octet-stream", true, v1.ResourceTypeData, "") assert.Nil(t, err) assert.Equal(t, base64Compressed, binaryResourceSpec.Content) @@ -485,7 +486,7 @@ func TestRunTextResource(t *testing.T) { func TestRunTextCompressedResource(t *testing.T) { data := []byte("hello horld") - base64Compressed, _ := compressToString(data) + base64Compressed, _ := source.CompressToString(data) textResourceSpec, err := binaryOrTextResource("file.ext", []byte("hello horld"), "text/plain", true, v1.ResourceTypeData, "") assert.Nil(t, err) assert.Equal(t, base64Compressed, textResourceSpec.Content) diff --git a/pkg/cmd/util_content.go b/pkg/cmd/source/content.go similarity index 85% rename from pkg/cmd/util_content.go rename to pkg/cmd/source/content.go index 67e706aaeb..28e359fffc 100644 --- a/pkg/cmd/util_content.go +++ b/pkg/cmd/source/content.go @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package source import ( "context" @@ -27,6 +27,7 @@ import ( "strings" "github.com/apache/camel-k/pkg/util" + "github.com/apache/camel-k/pkg/util/gzip" ) const ( @@ -36,11 +37,11 @@ const ( Kilobyte = 1 << 10 ) -func loadRawContent(ctx context.Context, source string) ([]byte, string, error) { +func LoadRawContent(ctx context.Context, source string) ([]byte, string, error) { var content []byte var err error - ok, err := isLocalAndFileExists(source) + ok, err := IsLocalAndFileExists(source) if err != nil { return nil, "", err } @@ -74,20 +75,29 @@ func loadRawContent(ctx context.Context, source string) ([]byte, string, error) return content, contentType, nil } -func isBinary(contentType string) bool { +func IsBinary(contentType string) bool { // According the http.DetectContentType method // also json and other "text" application mime types would be reported as text return !strings.HasPrefix(contentType, "text") } -func loadTextContent(ctx context.Context, source string, base64Compression bool) (string, string, bool, error) { - content, contentType, err := loadRawContent(ctx, source) +func CompressToString(content []byte) (string, error) { + bytes, err := gzip.CompressBase64(content) + if err != nil { + return "", err + } + + return string(bytes), nil +} + +func LoadTextContent(ctx context.Context, source string, base64Compression bool) (string, string, bool, error) { + content, contentType, err := LoadRawContent(ctx, source) if err != nil { return "", "", false, err } if base64Compression { - base64Compressed, err := compressToString(content) + base64Compressed, err := CompressToString(content) return base64Compressed, contentType, true, err } diff --git a/pkg/cmd/util_content_test.go b/pkg/cmd/source/content_test.go similarity index 83% rename from pkg/cmd/util_content_test.go rename to pkg/cmd/source/content_test.go index a0548c0ed8..1a3a9a7b63 100644 --- a/pkg/cmd/util_content_test.go +++ b/pkg/cmd/source/content_test.go @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package source import ( "context" @@ -31,7 +31,7 @@ import ( ) func TestRawContentFileMissing(t *testing.T) { - _, _, err := loadRawContent(context.Background(), "dsadas") + _, _, err := LoadRawContent(context.Background(), "dsadas") assert.NotNil(t, err) } @@ -44,10 +44,10 @@ func TestRawBinaryContentType(t *testing.T) { assert.Nil(t, tmpFile.Close()) assert.Nil(t, ioutil.WriteFile(tmpFile.Name(), []byte{1, 2, 3, 4, 5, 6}, 0o400)) - data, contentType, err := loadRawContent(context.Background(), tmpFile.Name()) + data, contentType, err := LoadRawContent(context.Background(), tmpFile.Name()) assert.Nil(t, err) assert.Equal(t, []byte{1, 2, 3, 4, 5, 6}, data) - assert.True(t, isBinary(contentType)) + assert.True(t, IsBinary(contentType)) } func TestRawApplicationContentType(t *testing.T) { @@ -59,10 +59,10 @@ func TestRawApplicationContentType(t *testing.T) { assert.Nil(t, tmpFile.Close()) assert.Nil(t, ioutil.WriteFile(tmpFile.Name(), []byte(`{"hello":"world"}`), 0o400)) - data, contentType, err := loadRawContent(context.Background(), tmpFile.Name()) + data, contentType, err := LoadRawContent(context.Background(), tmpFile.Name()) assert.Nil(t, err) assert.Equal(t, `{"hello":"world"}`, string(data)) - assert.False(t, isBinary(contentType)) + assert.False(t, IsBinary(contentType)) } func TestTextContentType(t *testing.T) { @@ -74,10 +74,10 @@ func TestTextContentType(t *testing.T) { assert.Nil(t, tmpFile.Close()) assert.Nil(t, ioutil.WriteFile(tmpFile.Name(), []byte(`{"hello":"world"}`), 0o400)) - data, contentType, compressed, err := loadTextContent(context.Background(), tmpFile.Name(), false) + data, contentType, compressed, err := LoadTextContent(context.Background(), tmpFile.Name(), false) assert.Nil(t, err) assert.Equal(t, `{"hello":"world"}`, data) - assert.False(t, isBinary(contentType)) + assert.False(t, IsBinary(contentType)) assert.False(t, compressed) } @@ -90,17 +90,17 @@ func TestTextCompressed(t *testing.T) { assert.Nil(t, tmpFile.Close()) assert.Nil(t, ioutil.WriteFile(tmpFile.Name(), []byte(`{"hello":"world"}`), 0o400)) - data, contentType, compressed, err := loadTextContent(context.Background(), tmpFile.Name(), true) + data, contentType, compressed, err := LoadTextContent(context.Background(), tmpFile.Name(), true) assert.Nil(t, err) assert.NotEqual(t, `{"hello":"world"}`, data) - assert.False(t, isBinary(contentType)) + assert.False(t, IsBinary(contentType)) assert.True(t, compressed) } func TestIsBinary(t *testing.T) { - assert.True(t, isBinary("image/jpeg")) - assert.True(t, isBinary("application/zip")) - assert.False(t, isBinary("text/plain")) + assert.True(t, IsBinary("image/jpeg")) + assert.True(t, IsBinary("application/zip")) + assert.False(t, IsBinary("text/plain")) } func TestContentHttp(t *testing.T) { diff --git a/pkg/cmd/util_sources.go b/pkg/cmd/source/source.go similarity index 77% rename from pkg/cmd/util_sources.go rename to pkg/cmd/source/source.go index b15e66912c..7af7f3600a 100644 --- a/pkg/cmd/util_sources.go +++ b/pkg/cmd/source/source.go @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package source import ( "context" @@ -45,9 +45,34 @@ type Source struct { Local bool } +// newSource creates a source using the content provider function. +func newSource(location string, compress bool, loadContent func() ([]byte, error)) (Source, error) { + // strip query part from location if any + locPath := util.SubstringBefore(location, "?") + if locPath == "" { + locPath = location + } + src := Source{ + Name: path.Base(locPath), + Origin: location, + Location: location, + Compress: compress, + } + + content, err := loadContent() + if err != nil { + return Source{}, err + } + if err := src.setContent(content); err != nil { + return Source{}, err + } + + return src, nil +} + func (s *Source) setContent(content []byte) error { if s.Compress { - result, err := compressToString(content) + result, err := CompressToString(content) if err != nil { return err } @@ -60,18 +85,18 @@ func (s *Source) setContent(content []byte) error { return nil } -// ResolveSources resolves sources from a variety of locations including local and remote. -func ResolveSources(ctx context.Context, locations []string, compress bool, cmd *cobra.Command) ([]Source, error) { +// Resolve resolves sources from a variety of locations including local and remote. +func Resolve(ctx context.Context, locations []string, compress bool, cmd *cobra.Command) ([]Source, error) { sources := make([]Source, 0, len(locations)) for _, location := range locations { - ok, err := isLocalAndFileExists(location) + ok, err := IsLocalAndFileExists(location) if err != nil { return sources, err } if ok { - answer, err := resolveLocalSource(location, compress) + answer, err := resolveLocal(location, compress) if err != nil { return sources, err } @@ -85,13 +110,13 @@ func ResolveSources(ctx context.Context, locations []string, compress bool, cmd switch { case u.Scheme == gistScheme || strings.HasPrefix(location, "https://gist.github.com/"): - answer, err := resolveGistSource(ctx, location, compress, cmd, u) + answer, err := resolveGist(ctx, location, compress, cmd, u) if err != nil { return sources, err } sources = append(sources, answer...) case u.Scheme == githubScheme: - answer, err := resolveSource(location, compress, func() ([]byte, error) { + answer, err := newSource(location, compress, func() ([]byte, error) { return loadContentGitHub(ctx, u) }) if err != nil { @@ -99,7 +124,7 @@ func ResolveSources(ctx context.Context, locations []string, compress bool, cmd } sources = append(sources, answer) case u.Scheme == httpScheme || u.Scheme == httpsScheme: - answer, err := resolveSource(location, compress, func() ([]byte, error) { + answer, err := newSource(location, compress, func() ([]byte, error) { return loadContentHTTP(ctx, u) }) if err != nil { @@ -115,8 +140,8 @@ func ResolveSources(ctx context.Context, locations []string, compress bool, cmd return sources, nil } -// resolveGistSource resolves sources from a Gist. -func resolveGistSource(ctx context.Context, location string, compress bool, cmd *cobra.Command, u *url.URL) ([]Source, error) { +// resolveGist resolves sources from a Gist. +func resolveGist(ctx context.Context, location string, compress bool, cmd *cobra.Command, u *url.URL) ([]Source, error) { var hc *http.Client if token, ok := os.LookupEnv("GITHUB_TOKEN"); ok { @@ -170,15 +195,15 @@ func resolveGistSource(ctx context.Context, location string, compress bool, cmd return sources, nil } -// resolveLocalSource resolves a source from the local file system. -func resolveLocalSource(location string, compress bool) (Source, error) { +// resolveLocal resolves a source from the local file system. +func resolveLocal(location string, compress bool) (Source, error) { if _, err := os.Stat(location); err != nil && os.IsNotExist(err) { return Source{}, errors.Wrapf(err, "file %s does not exist", location) } else if err != nil { return Source{}, errors.Wrapf(err, "error while accessing file %s", location) } - answer, err := resolveSource(location, compress, func() ([]byte, error) { + answer, err := newSource(location, compress, func() ([]byte, error) { return util.ReadFile(location) }) if err != nil { @@ -188,28 +213,3 @@ func resolveLocalSource(location string, compress bool) (Source, error) { return answer, nil } - -// resolveSource resolves a source using the content provider function. -func resolveSource(location string, compress bool, loadContent func() ([]byte, error)) (Source, error) { - // strip query part from location if any - locPath := util.SubstringBefore(location, "?") - if locPath == "" { - locPath = location - } - answer := Source{ - Name: path.Base(locPath), - Origin: location, - Location: location, - Compress: compress, - } - - content, err := loadContent() - if err != nil { - return Source{}, err - } - if err := answer.setContent(content); err != nil { - return Source{}, err - } - - return answer, nil -} diff --git a/pkg/cmd/source/util.go b/pkg/cmd/source/util.go new file mode 100644 index 0000000000..3e2b6a787b --- /dev/null +++ b/pkg/cmd/source/util.go @@ -0,0 +1,62 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package source + +import ( + "fmt" + "os" + "strings" + + "github.com/pkg/errors" +) + +const ( + // Supported source schemes. + gistScheme = "gist" + githubScheme = "github" + httpScheme = "http" + httpsScheme = "https" +) + +func IsLocalAndFileExists(uri string) (bool, error) { + if hasSupportedScheme(uri) { + // it's not a local file as it matches one of the supporting schemes + return false, nil + } + info, err := os.Stat(uri) + if err != nil { + if os.IsNotExist(err) { + return false, nil + } + // If it is a different error (ie, permission denied) we should report it back + return false, errors.Wrap(err, fmt.Sprintf("file system error while looking for %s", uri)) + } + + return !info.IsDir(), nil +} + +func hasSupportedScheme(uri string) bool { + if strings.HasPrefix(strings.ToLower(uri), gistScheme+":") || + strings.HasPrefix(strings.ToLower(uri), githubScheme+":") || + strings.HasPrefix(strings.ToLower(uri), httpScheme+":") || + strings.HasPrefix(strings.ToLower(uri), httpsScheme+":") { + return true + } + + return false +} diff --git a/pkg/cmd/util_test.go b/pkg/cmd/source/util_test.go similarity index 76% rename from pkg/cmd/util_test.go rename to pkg/cmd/source/util_test.go index 2d8734b356..53de90c9b9 100644 --- a/pkg/cmd/util_test.go +++ b/pkg/cmd/source/util_test.go @@ -18,7 +18,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package source import ( "testing" @@ -27,8 +27,8 @@ import ( ) func TestCorrectFileValuesButNotFound(t *testing.T) { - value1, err1 := isLocalAndFileExists("c:\\test") - value2, err2 := isLocalAndFileExists("path/to/file") + value1, err1 := IsLocalAndFileExists("c:\\test") + value2, err2 := IsLocalAndFileExists("path/to/file") // they are all not found, but it must not panic assert.Nil(t, err1) @@ -38,17 +38,17 @@ func TestCorrectFileValuesButNotFound(t *testing.T) { } func TestPermissionDenied(t *testing.T) { - value, err := isLocalAndFileExists("/root/test") + value, err := IsLocalAndFileExists("/root/test") // must not panic because a permission error assert.NotNil(t, err) assert.False(t, value) } func TestSupportedScheme(t *testing.T) { - gistValue, err1 := isLocalAndFileExists("gist:some/gist/resource") - githubValue, err2 := isLocalAndFileExists("github:some/github/resource") - httpValue, err3 := isLocalAndFileExists("http://some/http/resource") - httpsValue, err4 := isLocalAndFileExists("https://some/https/resource") + gistValue, err1 := IsLocalAndFileExists("gist:some/gist/resource") + githubValue, err2 := IsLocalAndFileExists("github:some/github/resource") + httpValue, err3 := IsLocalAndFileExists("http://some/http/resource") + httpsValue, err4 := IsLocalAndFileExists("https://some/https/resource") assert.Nil(t, err1) assert.False(t, gistValue) @@ -61,7 +61,7 @@ func TestSupportedScheme(t *testing.T) { } func TestUnSupportedScheme(t *testing.T) { - value, err := isLocalAndFileExists("bad_scheme:some/bad/resource") + value, err := IsLocalAndFileExists("bad_scheme:some/bad/resource") // must not report an error assert.Nil(t, err) assert.False(t, value) diff --git a/pkg/cmd/util.go b/pkg/cmd/util.go index 1dd67136a1..1736037f2a 100644 --- a/pkg/cmd/util.go +++ b/pkg/cmd/util.go @@ -24,17 +24,14 @@ import ( "fmt" "io" "log" - "os" "reflect" "strings" "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" v1 "github.com/apache/camel-k/pkg/apis/camel/v1" "github.com/apache/camel-k/pkg/client" platformutil "github.com/apache/camel-k/pkg/platform" - "github.com/apache/camel-k/pkg/util/gzip" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/spf13/viper" @@ -46,12 +43,6 @@ import ( const ( offlineCommandLabel = "camel.apache.org/cmd.offline" - - // Supported source schemes. - gistScheme = "gist" - githubScheme = "github" - httpScheme = "http" - httpsScheme = "https" ) // DeleteIntegration --. @@ -250,42 +241,6 @@ func fieldByMapstructureTagName(target reflect.Value, tagName string) (reflect.S return reflect.StructField{}, false } -func compressToString(content []byte) (string, error) { - bytes, err := gzip.CompressBase64(content) - if err != nil { - return "", err - } - - return string(bytes), nil -} - -func isLocalAndFileExists(uri string) (bool, error) { - if hasSupportedScheme(uri) { - // it's not a local file as it matches one of the supporting schemes - return false, nil - } - info, err := os.Stat(uri) - if err != nil { - if os.IsNotExist(err) { - return false, nil - } - // If it is a different error (ie, permission denied) we should report it back - return false, errors.Wrap(err, fmt.Sprintf("file system error while looking for %s", uri)) - } - return !info.IsDir(), nil -} - -func hasSupportedScheme(uri string) bool { - if strings.HasPrefix(strings.ToLower(uri), gistScheme+":") || - strings.HasPrefix(strings.ToLower(uri), githubScheme+":") || - strings.HasPrefix(strings.ToLower(uri), httpScheme+":") || - strings.HasPrefix(strings.ToLower(uri), httpsScheme+":") { - return true - } - - return false -} - func verifyOperatorID(ctx context.Context, client client.Client, operatorID string, out io.Writer) error { if pl, err := platformutil.LookupForPlatformName(ctx, client, operatorID); err != nil { if k8serrors.IsForbidden(err) { From 25102d0b9f5e5d4b9315de8aa2b61c5f23f914a6 Mon Sep 17 00:00:00 2001 From: Tadayoshi Sato Date: Fri, 29 Jul 2022 22:39:04 +0900 Subject: [PATCH 9/9] fix(e2e): stabilise kamel local e2e tests --- e2e/local/local_build_test.go | 2 ++ e2e/local/local_run_test.go | 9 ++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/e2e/local/local_build_test.go b/e2e/local/local_build_test.go index 2ea34f91b3..2c0f40c6dc 100644 --- a/e2e/local/local_build_test.go +++ b/e2e/local/local_build_test.go @@ -65,6 +65,7 @@ func TestLocalBuild(t *testing.T) { kamelBuild := KamelWithContext(ctx, "local", "build", file, "--image", image) kamelBuild.SetOut(pipew) + kamelBuild.SetErr(pipew) msgTagged := "Successfully tagged" logScanner := testutil.NewLogScanner(ctx, piper, msgTagged, image) @@ -94,6 +95,7 @@ func TestLocalBuildWithTrait(t *testing.T) { kamelBuild := KamelWithContext(ctx, "local", "build", file, "--image", image) kamelBuild.SetOut(pipew) + kamelBuild.SetErr(pipew) msgWarning := "Warning: traits are specified but don't take effect for local run: [jolokia.enabled=true]" msgTagged := "Successfully tagged" diff --git a/e2e/local/local_run_test.go b/e2e/local/local_run_test.go index c703e38250..cef5112b1f 100644 --- a/e2e/local/local_run_test.go +++ b/e2e/local/local_run_test.go @@ -23,7 +23,6 @@ package local import ( "context" "io" - "os" "strings" "testing" @@ -48,6 +47,7 @@ func TestLocalRun(t *testing.T) { kamelRun := KamelWithContext(ctx, "local", "run", file) kamelRun.SetOut(pipew) + kamelRun.SetErr(pipew) logScanner := testutil.NewLogScanner(ctx, piper, "Magicstring!") @@ -73,6 +73,7 @@ func TestLocalRunWithDependencies(t *testing.T) { kamelRun := KamelWithContext(ctx, "local", "run", file, "-d", "camel-amqp") kamelRun.SetOut(pipew) + kamelRun.SetErr(pipew) logScanner := testutil.NewLogScanner(ctx, piper, "Magicstring!") @@ -99,6 +100,7 @@ func TestLocalRunContainerize(t *testing.T) { kamelRun := KamelWithContext(ctx, "local", "run", file, "--image", image, "--containerize") kamelRun.SetOut(pipew) + kamelRun.SetErr(pipew) logScanner := testutil.NewLogScanner(ctx, piper, "Magicstring!") @@ -116,10 +118,6 @@ func TestLocalRunContainerize(t *testing.T) { func TestLocalRunIntegrationDirectory(t *testing.T) { RegisterTestingT(t) - if os.Getenv("CI") == "true" { - t.Skip("TODO: Temporarily disabled as this test is flaky and hangs the test process") - } - ctx1, cancel1 := context.WithCancel(TestContext) defer cancel1() @@ -146,6 +144,7 @@ func TestLocalRunIntegrationDirectory(t *testing.T) { kamelRun := KamelWithContext(ctx2, "local", "run", "--integration-directory", dir) kamelRun.SetOut(pipew) + kamelRun.SetErr(pipew) logScanner := testutil.NewLogScanner(ctx2, piper, "Magicstring!")