diff --git a/cmd/analyze.go b/cmd/analyze.go index 3753ad6..e305044 100644 --- a/cmd/analyze.go +++ b/cmd/analyze.go @@ -29,15 +29,15 @@ import ( var ( // application source path inside the container - SourceMountPath = filepath.Join(InputPath, "source") + SourceMountPath = path.Join(InputPath, "source") // analyzer config files - ConfigMountPath = filepath.Join(InputPath, "config") + ConfigMountPath = path.Join(InputPath, "config") // user provided rules path - RulesMountPath = filepath.Join(RulesetPath, "input") + RulesMountPath = path.Join(RulesetPath, "input") // paths to files in the container - AnalysisOutputMountPath = filepath.Join(OutputPath, "output.yaml") - DepsOutputMountPath = filepath.Join(OutputPath, "dependencies.yaml") - ProviderSettingsMountPath = filepath.Join(ConfigMountPath, "settings.json") + AnalysisOutputMountPath = path.Join(OutputPath, "output.yaml") + DepsOutputMountPath = path.Join(OutputPath, "dependencies.yaml") + ProviderSettingsMountPath = path.Join(ConfigMountPath, "settings.json") ) // kantra analyze flags @@ -119,7 +119,7 @@ func NewAnalyzeCmd(log logr.Logger) *cobra.Command { } err := analyzeCmd.Clean(cmd.Context()) if err != nil { - log.Error(err, "failed to generate static report") + log.Error(err, "failed to clean temporary container resources") return err } return nil @@ -170,7 +170,7 @@ func (a *analyzeCommand) Validate() error { return fmt.Errorf("%w failed to get absolute path for input file %s", err, a.input) } // make sure we mount a file and not a dir - SourceMountPath = filepath.Join(SourceMountPath, filepath.Base(a.input)) + SourceMountPath = path.Join(SourceMountPath, filepath.Base(a.input)) a.isFileInput = true } if a.mode != string(provider.FullAnalysisMode) && @@ -333,7 +333,7 @@ func (a *analyzeCommand) getConfigVolumes() (map[string]string, error) { // only java provider can work with binaries, all others // continue pointing to the directory instead of file if a.isFileInput { - otherProvsMountPath = filepath.Dir(otherProvsMountPath) + otherProvsMountPath = path.Dir(otherProvsMountPath) } javaConfig := provider.Config{ @@ -436,7 +436,7 @@ func (a *analyzeCommand) getRulesVolumes() (map[string]string, error) { } } else { - rulesVolumes[r] = filepath.Join(RulesMountPath, filepath.Base(r)) + rulesVolumes[r] = path.Join(RulesMountPath, filepath.Base(r)) } } if rulesetNeeded { @@ -446,7 +446,7 @@ func (a *analyzeCommand) getRulesVolumes() (map[string]string, error) { a.log.V(1).Error(err, "failed to create temp ruleset", "path", tempRulesetPath) return nil, err } - rulesVolumes[tempDir] = filepath.Join(RulesMountPath, filepath.Base(tempDir)) + rulesVolumes[tempDir] = path.Join(RulesMountPath, filepath.Base(tempDir)) } return rulesVolumes, nil } @@ -494,7 +494,7 @@ func (a *analyzeCommand) RunAnalysis(ctx context.Context, xmlOutputDir string) e } if xmlOutputDir != "" { - convertPath := filepath.Join(RulesetPath, "convert") + convertPath := path.Join(RulesetPath, "convert") volumes[xmlOutputDir] = convertPath // for cleanup purposes a.tempDirs = append(a.tempDirs, xmlOutputDir) @@ -584,44 +584,40 @@ func (a *analyzeCommand) GenerateStaticReport(ctx context.Context) error { if a.skipStaticReport { return nil } - volumes := map[string]string{ a.input: SourceMountPath, a.output: OutputPath, } - - args := []string{ + args := []string{} + staticReportArgs := []string{"/usr/local/bin/js-bundle-generator", fmt.Sprintf("--analysis-output-list=%s", AnalysisOutputMountPath), fmt.Sprintf("--deps-output-list=%s", DepsOutputMountPath), - fmt.Sprintf("--output-path=%s", filepath.Join("/usr/local/static-report/output.js")), + fmt.Sprintf("--output-path=%s", path.Join("/usr/local/static-report/output.js")), fmt.Sprintf("--application-name-list=%s", filepath.Base(a.input)), } + cpArgs := []string{"&& cp -r", + "/usr/local/static-report", OutputPath} + + args = append(args, staticReportArgs...) + args = append(args, cpArgs...) + + joinedArgs := strings.Join(args, " ") + staticReportCmd := []string{joinedArgs} - a.log.Info("generating static report", - "output", a.output, "args", strings.Join(args, " ")) container := NewContainer(a.log) + a.log.Info("generating static report", + "output", a.output, "args", strings.Join(staticReportCmd, " ")) err := container.Run( ctx, - WithEntrypointBin("/usr/local/bin/js-bundle-generator"), - WithEntrypointArgs(args...), + WithEntrypointBin("/bin/sh"), + WithEntrypointArgs(staticReportCmd...), WithVolumes(volumes), - // keep container to copy static report - WithCleanup(false), + WithcFlag(true), ) if err != nil { return err } - err = container.Cp(ctx, "/usr/local/static-report", a.output) - if err != nil { - return err - } - - err = container.Rm(ctx) - if err != nil { - return err - } - return nil } @@ -712,7 +708,7 @@ func (a *analyzeCommand) getXMLRulesVolumes(tempRuleDir string) (map[string]stri return nil, err } } else { - rulesVolumes[r] = filepath.Join(XMLRulePath, filepath.Base(r)) + rulesVolumes[r] = path.Join(XMLRulePath, filepath.Base(r)) } } if mountTempDir { diff --git a/cmd/container.go b/cmd/container.go index 0e2ead8..9bd61ba 100644 --- a/cmd/container.go +++ b/cmd/container.go @@ -8,6 +8,7 @@ import ( "math/rand" "os" "os/exec" + "path" "path/filepath" "runtime" "strings" @@ -29,6 +30,7 @@ type container struct { cleanup bool // map of source -> dest paths to mount volumes map[string]string + cFlag bool log logr.Logger } @@ -82,6 +84,12 @@ func WithStderr(e ...io.Writer) Option { } } +func WithcFlag(cl bool) Option { + return func(c *container) { + c.cFlag = cl + } +} + func WithCleanup(cl bool) Option { return func(c *container) { c.cleanup = cl @@ -115,6 +123,7 @@ func NewContainer(log logr.Logger) *container { name: randomName(), // by default, remove the container after run() cleanup: true, + cFlag: false, log: log, } } @@ -169,10 +178,10 @@ func (c *container) Run(ctx context.Context, opts ...Option) error { // TODO: check this on windows if os == "linux" { args = append(args, fmt.Sprintf("%s:%s:Z", - filepath.Clean(sourcePath), filepath.Clean(destPath))) + filepath.Clean(sourcePath), path.Clean(destPath))) } else { args = append(args, fmt.Sprintf("%s:%s", - filepath.Clean(sourcePath), filepath.Clean(destPath))) + filepath.Clean(sourcePath), path.Clean(destPath))) } } for k, v := range c.env { @@ -180,6 +189,9 @@ func (c *container) Run(ctx context.Context, opts ...Option) error { args = append(args, fmt.Sprintf("%s=%s", k, v)) } args = append(args, c.image) + if c.cFlag { + args = append(args, "-c") + } if len(c.entrypointArgs) > 0 { args = append(args, c.entrypointArgs...) } diff --git a/cmd/shimconvert.go b/cmd/shimconvert.go index a54333e..e752987 100644 --- a/cmd/shimconvert.go +++ b/cmd/shimconvert.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "os" + "path" "path/filepath" "strings" @@ -108,7 +109,7 @@ func (w *windupShimCommand) getRulesVolumes(tempRuleDir string) (map[string]stri return nil, err } } else { - rulesVolumes[r] = filepath.Join(XMLRulePath, filepath.Base(r)) + rulesVolumes[r] = path.Join(XMLRulePath, filepath.Base(r)) } } if mountTempDir { diff --git a/test-data/analysis-output.yaml b/test-data/analysis-output.yaml index c9f0c89..c2fceda 100644 --- a/test-data/analysis-output.yaml +++ b/test-data/analysis-output.yaml @@ -1435,73 +1435,6 @@ - Java Remote Method Invocation (RMI) service - rmi - Java Remote Method Invocation (RMI) API - violations: - jni-native-code-00000: - description: |- - Java native libraries (JNI, JNA) - Java native libraries might not run in a cloud or container environment.. Recommendations. * Review the purpose of the native library in your application.. * Check whether the native library is compatible with a cloud environment.. * Reuse or embed the native library or application in a cloud environment, for example, in a JBoss module.. * Replace, remove, or rewrite the native library or application using a cloud-compatible equivalent. - category: mandatory - labels: - - konveyor.io/target=cloud-readiness - - konveyor.io/source - - jni - incidents: - - uri: konveyor-jdt://contents/root/.m2/repository/io/konveyor/demo/config-utils/1.0.0/config-utils-1.0.0.jar?packageName=io.konveyor.demo.config.ApplicationConfiguration.class&source-range=true - message: Java native libraries might not run in a cloud or container environment.. Recommendations. * Review the purpose of the native library in your application.. * Check whether the native library is compatible with a cloud environment.. * Reuse or embed the native library or application in a cloud environment, for example, in a JBoss module.. * Replace, remove, or rewrite the native library or application using a cloud-compatible equivalent. - codeSnip: " 1 package io.konveyor.demo.config;\n 2 \n 3 import java.io.FileInputStream;\n 4 import java.io.InputStream;\n 5 import java.util.Properties;\n 6 \n 7 public class ApplicationConfiguration {\n 8 \n 9 \tprivate Properties config;\n 10 \n 11 \tpublic ApplicationConfiguration() {\n 12 \t\tsuper();\n 13 \t\tthis.config = loadProperties();\n 14 \n 15 \t}\n 16 \n 17 \tprivate Properties loadProperties() {\n 18 \t\tProperties properties = new Properties();\n 19 \n 20 \t\ttry (InputStream inputStream = new FileInputStream(\"/opt/config/persistence.properties\")) {\n 21 \n 22 \t\t\tproperties.load(inputStream);\n 23 \n 24 \t\t} catch (Exception e) {\n 25 \t\t\tSystem.out.println(\"Exception: \" + e);\n 26 \t\t}\n 27 \n 28 \t\treturn properties;\n 29 \t}\n 30 \n 31 \tpublic String getProperty (String name) {\n 32 \t\treturn config.getProperty(name);\n 33 \t}\n 34 \n 35 \n 36 \n 37 }\n" - lineNumber: 12 - variables: - file: konveyor-jdt://contents/root/.m2/repository/io/konveyor/demo/config-utils/1.0.0/config-utils-1.0.0.jar?packageName=io.konveyor.demo.config.ApplicationConfiguration.class&source-range=true - kind: Constructor - name: ApplicationConfiguration - - uri: konveyor-jdt://contents/root/.m2/repository/io/konveyor/demo/config-utils/1.0.0/config-utils-1.0.0.jar?packageName=io.konveyor.demo.config.ApplicationConfiguration.class&source-range=true - message: Java native libraries might not run in a cloud or container environment.. Recommendations. * Review the purpose of the native library in your application.. * Check whether the native library is compatible with a cloud environment.. * Reuse or embed the native library or application in a cloud environment, for example, in a JBoss module.. * Replace, remove, or rewrite the native library or application using a cloud-compatible equivalent. - codeSnip: " 1 package io.konveyor.demo.config;\n 2 \n 3 import java.io.FileInputStream;\n 4 import java.io.InputStream;\n 5 import java.util.Properties;\n 6 \n 7 public class ApplicationConfiguration {\n 8 \n 9 \tprivate Properties config;\n 10 \n 11 \tpublic ApplicationConfiguration() {\n 12 \t\tsuper();\n 13 \t\tthis.config = loadProperties();\n 14 \n 15 \t}\n 16 \n 17 \tprivate Properties loadProperties() {\n 18 \t\tProperties properties = new Properties();\n 19 \n 20 \t\ttry (InputStream inputStream = new FileInputStream(\"/opt/config/persistence.properties\")) {\n 21 \n 22 \t\t\tproperties.load(inputStream);\n 23 \n 24 \t\t} catch (Exception e) {\n 25 \t\t\tSystem.out.println(\"Exception: \" + e);\n 26 \t\t}\n 27 \n 28 \t\treturn properties;\n 29 \t}\n 30 \n 31 \tpublic String getProperty (String name) {\n 32 \t\treturn config.getProperty(name);\n 33 \t}\n 34 \n 35 \n 36 \n 37 }\n" - lineNumber: 21 - variables: - file: konveyor-jdt://contents/root/.m2/repository/io/konveyor/demo/config-utils/1.0.0/config-utils-1.0.0.jar?packageName=io.konveyor.demo.config.ApplicationConfiguration.class&source-range=true - kind: Method - name: loadProperties - links: - - url: https://access.redhat.com/solutions/229443 - title: How to load native libraries and access them via JNI in EAP (with or without a module) - - url: https://access.redhat.com/solutions/1444643 - title: Is it supported to compile the JNI code as 32-bit shared libraries and use it in 64-bit compiled Java code ? - extras: [] - effort: 7 - local-storage-00001: - description: |- - File system - Java IO - An application running inside a container could lose access to a file in local storage.. Recommendations. The following recommendations depend on the function of the file in local storage:. * Logging: Log to standard output and use a centralized log collector to analyze the logs.. * Caching: Use a cache backing service.. * Configuration: Store configuration settings in environment variables so that they can be updated without code changes.. * Data storage: Use a database backing service for relational data or use a persistent data storage system.. * Temporary data storage: Use the file system of a running container as a brief, single-transaction cache. - category: mandatory - labels: - - konveyor.io/target=cloud-readiness - - konveyor.io/source - - storage - incidents: - - uri: konveyor-jdt://contents/root/.m2/repository/io/konveyor/demo/config-utils/1.0.0/config-utils-1.0.0.jar?packageName=io.konveyor.demo.config.ApplicationConfiguration.class&source-range=true - message: 'An application running inside a container could lose access to a file in local storage.. Recommendations. The following recommendations depend on the function of the file in local storage:. * Logging: Log to standard output and use a centralized log collector to analyze the logs.. * Caching: Use a cache backing service.. * Configuration: Store configuration settings in environment variables so that they can be updated without code changes.. * Data storage: Use a database backing service for relational data or use a persistent data storage system.. * Temporary data storage: Use the file system of a running container as a brief, single-transaction cache.' - codeSnip: " 1 package io.konveyor.demo.config;\n 2 \n 3 import java.io.FileInputStream;\n 4 import java.io.InputStream;\n 5 import java.util.Properties;\n 6 \n 7 public class ApplicationConfiguration {\n 8 \n 9 \tprivate Properties config;\n 10 \n 11 \tpublic ApplicationConfiguration() {\n 12 \t\tsuper();\n 13 \t\tthis.config = loadProperties();\n 14 \n 15 \t}\n 16 \n 17 \tprivate Properties loadProperties() {\n 18 \t\tProperties properties = new Properties();\n 19 \n 20 \t\ttry (InputStream inputStream = new FileInputStream(\"/opt/config/persistence.properties\")) {\n 21 \n 22 \t\t\tproperties.load(inputStream);\n 23 \n 24 \t\t} catch (Exception e) {\n 25 \t\t\tSystem.out.println(\"Exception: \" + e);\n 26 \t\t}\n 27 \n 28 \t\treturn properties;\n 29 \t}\n 30 \n 31 \tpublic String getProperty (String name) {\n 32 \t\treturn config.getProperty(name);\n 33 \t}\n 34 \n 35 \n 36 \n 37 }\n" - lineNumber: 19 - variables: - file: konveyor-jdt://contents/root/.m2/repository/io/konveyor/demo/config-utils/1.0.0/config-utils-1.0.0.jar?packageName=io.konveyor.demo.config.ApplicationConfiguration.class&source-range=true - kind: Constructor - name: loadProperties - links: - - url: https://12factor.net/logs - title: 'Twelve-Factor App: Logs' - - url: https://docs.openshift.com/container-platform/4.5/logging/cluster-logging.html - title: 'OpenShift Container Platform: Understanding cluster logging' - - url: https://12factor.net/backing-services - title: 'Twelve-Factor App: Backing services' - - url: https://12factor.net/config - title: 'Twelve-Factor App: Config' - - url: https://docs.openshift.com/container-platform/4.5/builds/creating-build-inputs.html#builds-input-secrets-configmaps_creating-build-inputs - title: 'OpenShift Container Platform: Input secrets and ConfigMaps' - - url: https://docs.openshift.com/container-platform/4.5/storage/understanding-persistent-storage.html - title: 'OpenShift Container Platform: Understanding persistent storage' - extras: [] - effort: 1 unmatched: - embedded-cache-libraries-01000 - embedded-cache-libraries-02000 @@ -1521,19 +1454,21 @@ - logging-0000 - logging-0001 - jca-00000 - - local-storage-00003 - local-storage-00004 - - session-00000 + - local-storage-00003 - java-rmi-00000 + - session-00000 - logging-0001 - - java-rpc-00000 - logging-0000 + - java-rpc-00000 - socket-communication-00001 - - mail-00000 - - session-00001 - - local-storage-00002 - local-storage-00005 - socket-communication-00000 + - local-storage-00001 + - jni-native-code-00000 + - session-00001 + - mail-00000 + - local-storage-00002 - name: os/windows description: This is a ruleset for Windows operating system specific rules while migrating to Linux operating system. skipped: