Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ adding ability to run dep command during analysis command #531

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions .github/workflows/demo-testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,21 @@ jobs:

- name: run demo image and ensure violations output unchanged
run: |
podman run -v $(pwd)/demo-output.yaml:/analyzer-lsp/output.yaml:Z localhost/testing:latest
podman run --entrypoint /usr/bin/konveyor-analyzer -v $(pwd)/demo-dep-output.yaml:/analyzer-lsp/demo-dep-output.yaml:Z -v $(pwd)/demo-output.yaml:/analyzer-lsp/output.yaml:Z localhost/testing:latest --dep-output-file=demo-dep-output.yaml
diff \
<(yq -P 'sort_keys(..)' -o=props <(git show HEAD:demo-output.yaml)) \
<(yq -P 'sort_keys(..)' -o=props <(cat demo-output.yaml))

- name: run demo image and ensure dependency output unchanged
run: |
podman run --entrypoint /usr/bin/konveyor-analyzer-dep -v $(pwd)/demo-dep-output.yaml:/analyzer-lsp/demo-dep-output.yaml:Z localhost/testing:latest --output-file=demo-dep-output.yaml
diff \
<(yq -P 'sort_keys(..)' -o=props <(git show HEAD:demo-dep-output.yaml)) \
<(yq -P 'sort_keys(..)' -o=props <(cat demo-dep-output.yaml))

# - name: run demo image and ensure dependency output unchanged
# run: |
# podman run --entrypoint /usr/bin/konveyor-analyzer-dep -v $(pwd)/demo-dep-output.yaml:/analyzer-lsp/demo-dep-output.yaml:Z localhost/testing:latest --output-file=demo-dep-output.yaml --dep-output-file=de
# diff \
# <(yq -P 'sort_keys(..)' -o=props <(git show HEAD:demo-dep-output.yaml)) \
# <(yq -P 'sort_keys(..)' -o=props <(cat demo-dep-output.yaml))

- uses: actions/checkout@v3
with:
fetch-depth: 0
Expand Down
105 changes: 105 additions & 0 deletions cmd/analyzer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"os"
"sort"
"strings"
"sync"

logrusr "github.com/bombsimon/logrusr/v3"
"github.com/go-logr/logr"
Expand All @@ -21,6 +22,7 @@ import (
"github.com/spf13/cobra"
"github.com/swaggest/openapi-go/openapi3"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"gopkg.in/yaml.v2"
)

Expand All @@ -45,6 +47,8 @@ var (
noDependencyRules bool
contextLines int
getOpenAPISpec string
treeOutput bool
depOutputFile string
)

func AnalysisCmd() *cobra.Command {
Expand Down Expand Up @@ -205,8 +209,22 @@ func AnalysisCmd() *cobra.Command {
initSpan.End()
}

wg := &sync.WaitGroup{}
var depSpan trace.Span
var depCtx context.Context
if depOutputFile != "" {
depCtx, depSpan = tracing.StartNewSpan(ctx, "dep")
wg.Add(1)
go DependencyOutput(depCtx, providers, log, errLog, depOutputFile, dependencyLabelSelector, wg)
}

// This will already wait
rulesets := eng.RunRules(ctx, ruleSets, selectors...)
engineSpan.End()
wg.Wait()
if depSpan != nil {
depSpan.End()
}
eng.Stop()

for _, provider := range needProviders {
Expand Down Expand Up @@ -248,6 +266,8 @@ func AnalysisCmd() *cobra.Command {
rootCmd.Flags().BoolVar(&noDependencyRules, "no-dependency-rules", false, "Disable dependency analysis rules")
rootCmd.Flags().IntVar(&contextLines, "context-lines", 10, "When violation occurs, A part of source code is added to the output, So this flag configures the number of source code lines to be printed to the output.")
rootCmd.Flags().StringVar(&getOpenAPISpec, "get-openapi-spec", "", "Get the openAPI spec for the rulesets, rules and provider capabilities and put in file passed in.")
rootCmd.Flags().BoolVar(&treeOutput, "tree", false, "output dependencies as a tree")
rootCmd.Flags().StringVar(&depOutputFile, "dep-output-file", "", "path to dependency output file")

return rootCmd
}
Expand Down Expand Up @@ -399,3 +419,88 @@ func createOpenAPISchema(providers map[string]provider.InternalProviderClient, l

return sc
}

func DependencyOutput(ctx context.Context, providers map[string]provider.InternalProviderClient, log logr.Logger, errLog logr.Logger, depOutputFile string, labelSelector *labels.LabelSelector[*konveyor.Dep], wg *sync.WaitGroup) {
defer wg.Done()
var depsFlat []konveyor.DepsFlatItem
var depsTree []konveyor.DepsTreeItem
for name, prov := range providers {
if !provider.HasCapability(prov.Capabilities(), "dependency") {
log.Info("provider does not have dependency capability", "provider", name)
continue
}

if treeOutput {
deps, err := prov.GetDependenciesDAG(ctx)
if err != nil {
errLog.Error(err, "failed to get list of dependencies for provider", "provider", name)
continue
}
for u, ds := range deps {
depsTree = append(depsTree, konveyor.DepsTreeItem{
FileURI: string(u),
Provider: name,
Dependencies: ds,
})
}
} else {
deps, err := prov.GetDependencies(ctx)
if err != nil {
errLog.Error(err, "failed to get list of dependencies for provider", "provider", name)
continue
}
for u, ds := range deps {
newDeps := ds
if labelSelector != nil {
newDeps, err = labelSelector.MatchList(ds)
if err != nil {
errLog.Error(err, "error matching label selector on deps")
continue
}
}
depsFlat = append(depsFlat, konveyor.DepsFlatItem{
Provider: name,
FileURI: string(u),
Dependencies: newDeps,
})
}
}
}

if depsFlat == nil && depsTree == nil {
errLog.Info("failed to get dependencies from all given providers")
os.Exit(1)
}

var b []byte
var err error
if treeOutput {
b, err = yaml.Marshal(depsTree)
if err != nil {
errLog.Error(err, "failed to marshal dependency data as yaml")
os.Exit(1)
}
} else {
// Sort depsFlat
sort.SliceStable(depsFlat, func(i, j int) bool {
if depsFlat[i].Provider == depsFlat[j].Provider {
return depsFlat[i].FileURI < depsFlat[j].FileURI
} else {
return depsFlat[i].Provider < depsFlat[j].Provider
}
})

b, err = yaml.Marshal(depsFlat)
if err != nil {
errLog.Error(err, "failed to marshal dependency data as yaml")
os.Exit(1)
}
}

err = os.WriteFile(depOutputFile, b, 0644)
if err != nil {
errLog.Error(err, "failed to write dependencies to output file", "file", depOutputFile)
os.Exit(1)
}

}
Loading