Skip to content

Commit

Permalink
Containerless support for Java apps (#338)
Browse files Browse the repository at this point in the history
* containerless support for java

Signed-off-by: Emily McMullan <[email protected]>

* clean up run func

Signed-off-by: Emily McMullan <[email protected]>

* remove static report script

Signed-off-by: Emily McMullan <[email protected]>

---------

Signed-off-by: Emily McMullan <[email protected]>
  • Loading branch information
eemcmullan authored Sep 30, 2024
1 parent 150d744 commit cafa2f2
Show file tree
Hide file tree
Showing 10 changed files with 1,210 additions and 114 deletions.
857 changes: 857 additions & 0 deletions cmd/analyze-bin.go

Large diffs are not rendered by default.

99 changes: 14 additions & 85 deletions cmd/analyze.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package cmd

import (
"bufio"
"bytes"
"context"
"encoding/json"
Expand All @@ -17,7 +16,6 @@ import (

"path/filepath"
"slices"
"sort"
"strings"

"github.com/devfile/alizer/pkg/apis/model"
Expand Down Expand Up @@ -70,6 +68,17 @@ var (
}
)

// analyzer container paths
const (
RulesetPath = "/opt/rulesets"
OpenRewriteRecipesPath = "/opt/openrewrite"
InputPath = "/opt/input"
OutputPath = "/opt/output"
XMLRulePath = "/opt/xmlrules"
ShimOutputPath = "/opt/shimoutput"
CustomRulePath = "/opt/input/rules"
)

// supported providers
const (
javaProvider = "java"
Expand All @@ -88,15 +97,6 @@ const (
ClassFile = ".class"
)

// provider config options
const (
mavenSettingsFile = "mavenSettingsFile"
lspServerPath = "lspServerPath"
lspServerName = "lspServerName"
workspaceFolders = "workspaceFolders"
dependencyProviderPath = "dependencyProviderPath"
)

// TODO add network and volume w/ interface
type ProviderInit struct {
port int
Expand Down Expand Up @@ -664,7 +664,7 @@ func (a *analyzeCommand) fetchLabels(ctx context.Context, listSources, listTarge
runModeContainer := "container"
if os.Getenv(runMode) == runModeContainer {
if listSources {
sourceSlice, err := readRuleFilesForLabels(sourceLabel)
sourceSlice, err := a.readRuleFilesForLabels(sourceLabel)
if err != nil {
a.log.Error(err, "failed to read rule labels")
return err
Expand All @@ -673,7 +673,7 @@ func (a *analyzeCommand) fetchLabels(ctx context.Context, listSources, listTarge
return nil
}
if listTargets {
targetsSlice, err := readRuleFilesForLabels(targetLabel)
targetsSlice, err := a.readRuleFilesForLabels(targetLabel)
if err != nil {
a.log.Error(err, "failed to read rule labels")
return err
Expand Down Expand Up @@ -713,7 +713,7 @@ func (a *analyzeCommand) fetchLabels(ctx context.Context, listSources, listTarge
return nil
}

func readRuleFilesForLabels(label string) ([]string, error) {
func (a *analyzeCommand) readRuleFilesForLabels(label string) ([]string, error) {
labelsSlice := []string{}
err := filepath.WalkDir(RulesetPath, walkRuleSets(RulesetPath, label, &labelsSlice))
if err != nil {
Expand All @@ -722,77 +722,6 @@ func readRuleFilesForLabels(label string) ([]string, error) {
return labelsSlice, nil
}

func walkRuleSets(root string, label string, labelsSlice *[]string) fs.WalkDirFunc {
return func(path string, d fs.DirEntry, err error) error {
if !d.IsDir() {
*labelsSlice, err = readRuleFile(path, labelsSlice, label)
if err != nil {
return err
}
}
return err
}
}

func readRuleFile(filePath string, labelsSlice *[]string, label string) ([]string, error) {
file, err := os.Open(filePath)
if err != nil {
return nil, err
}
defer file.Close()

scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanWords)

for scanner.Scan() {
// add source/target labels to slice
label := getSourceOrTargetLabel(scanner.Text(), label)
if len(label) > 0 && !slices.Contains(*labelsSlice, label) {
*labelsSlice = append(*labelsSlice, label)
}
}
if err := scanner.Err(); err != nil {
return nil, err
}
return *labelsSlice, nil
}

func getSourceOrTargetLabel(text string, label string) string {
if strings.Contains(text, label) {
return text
}
return ""
}

func listOptionsFromLabels(sl []string, label string, out io.Writer) {
var newSl []string
l := label + "="

for _, label := range sl {
newSt := strings.TrimPrefix(label, l)

if newSt != label {
newSt = strings.TrimSuffix(newSt, "+")
newSt = strings.TrimSuffix(newSt, "-")

if !slices.Contains(newSl, newSt) {
newSl = append(newSl, newSt)

}
}
}
sort.Strings(newSl)

if label == outputv1.SourceTechnologyLabel {
fmt.Fprintln(out, "available source technologies:")
} else {
fmt.Fprintln(out, "available target technologies:")
}
for _, tech := range newSl {
fmt.Fprintln(out, tech)
}
}

func (a *analyzeCommand) getDepsFolders() (map[string]string, []string) {
vols := map[string]string{}
dependencyFolders := []string{}
Expand Down
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func init() {
rootCmd.AddCommand(NewAnalyzeCmd(logger))
rootCmd.AddCommand(NewTestCommand(logger))
rootCmd.AddCommand(NewVersionCommand())
rootCmd.AddCommand(NewAnalyzeBinCmd(logger))
}

// Execute adds all child commands to the root command and sets flags appropriately.
Expand Down
10 changes: 0 additions & 10 deletions cmd/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,6 @@ import (

var Settings = &Config{}

const (
RulesetPath = "/opt/rulesets"
OpenRewriteRecipesPath = "/opt/openrewrite"
InputPath = "/opt/input"
OutputPath = "/opt/output"
XMLRulePath = "/opt/xmlrules"
ShimOutputPath = "/opt/shimoutput"
CustomRulePath = "/opt/input/rules"
)

type Config struct {
RootCommandName string `env:"CMD_NAME" default:"kantra"`
ContainerBinary string `env:"CONTAINER_TOOL" default:"/usr/bin/podman"`
Expand Down
121 changes: 121 additions & 0 deletions cmd/static-report.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package cmd

import (
"encoding/json"
"fmt"
"log"
"os"
"text/template"

"github.com/konveyor/analyzer-lsp/output/v1/konveyor"
"gopkg.in/yaml.v2"
)

// taken from https://github.com/konveyor/static-report/blob/main/analyzer-output-parser/main.go

type Application struct {
Id string `yaml:"id" json:"id"`
Name string `yaml:"name" json:"name"`
Rulesets []konveyor.RuleSet `yaml:"rulesets" json:"rulesets"`
DepItems []konveyor.DepsFlatItem `yaml:"depItems" json:"depItems"`

analysisPath string `yaml:"-" json:"-"`
depsPath string `yaml:"-" json:"-"`
}

func validateFlags(analysisOutputPaths []string, appNames []string, depsOutputs []string) ([]*Application, error) {
var applications []*Application
if len(analysisOutputPaths) == 0 {
return nil, fmt.Errorf("analysis output paths required")
}
if len(appNames) == 0 {
return nil, fmt.Errorf("application names required")
}
if len(depsOutputs) == 0 {
log.Println("dependency output path not provided, only parsing analysis output")
}
for idx, analysisPath := range analysisOutputPaths {
currApp := &Application{
Id: fmt.Sprintf("%04d", idx),
Rulesets: make([]konveyor.RuleSet, 0),
DepItems: make([]konveyor.DepsFlatItem, 0),
analysisPath: analysisPath,
}
if len(depsOutputs) > 0 {
currApp.depsPath = depsOutputs[idx]
}
currApp.Name = appNames[idx]
applications = append(applications, currApp)
}

return applications, nil
}

// loadApplications loads applications from provider config
func loadApplications(apps []*Application) error {
for _, app := range apps {
analysisReport, err := os.ReadFile(app.analysisPath)
if err != nil {
return err
}
err = yaml.Unmarshal(analysisReport, &app.Rulesets)
if err != nil {
return err
}
if app.depsPath != "" {
depsReport, err := os.ReadFile(app.depsPath)
if err != nil {
return err
}

err = yaml.Unmarshal(depsReport, &app.DepItems)
if err != nil {
return err
}
// extras on dependencies trip JSON marshaling
// we don't need them in the report, ignore them
for idx := range app.DepItems {
depItem := &app.DepItems[idx]
for _, dep := range depItem.Dependencies {
dep.Extras = make(map[string]interface{})
}
}
}
// extras on incidents trip JSON marshaling
// we don't need them in the report, ignore them
for idx := range app.Rulesets {
rs := &app.Rulesets[idx]
for _, violation := range rs.Violations {
violation.Extras = nil
for idx := range violation.Incidents {
inc := &violation.Incidents[idx]
inc.Variables = make(map[string]interface{})
}
}
}
}

return nil
}

func generateJSBundle(apps []*Application, outputPath string) error {
output, err := json.Marshal(apps)
if err != nil {
log.Fatal("failed to marshal applications", err)
}

tmpl := template.Must(template.New("").Parse(`
window["apps"] = {{.Apps}}
`))
file, err := os.Create(outputPath)
if err != nil {
log.Fatal("failed to create JS output bundle", err)
}
defer file.Close()
err = tmpl.Execute(file, struct {
Apps string
}{
Apps: string(output),
})
return err
}
Loading

0 comments on commit cafa2f2

Please sign in to comment.