diff --git a/cmd/analyzer/main.go b/cmd/analyzer/main.go index 5e6d446e..c0ec330c 100644 --- a/cmd/analyzer/main.go +++ b/cmd/analyzer/main.go @@ -356,6 +356,12 @@ func createOpenAPISchema(providers map[string]provider.InternalProviderClient, l Ref: fmt.Sprintf("#/components/schemas/%s.%s", provName, c.Name), }, }) + // Only add output schemas for capabilities that have defined them. + if c.Output.Schema != nil && len(c.Output.Schema.Properties) != 0 { + spec.MapOfSchemaOrRefValues[fmt.Sprintf("%s.%s-out", provName, c.Name)] = openapi3.SchemaOrRef{ + Schema: c.Output.Schema, + } + } } } diff --git a/docs/rules.md b/docs/rules.md index 5ed1a402..5dd63b54 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -287,6 +287,8 @@ when: You can also chain the variables from one condition to be used as input in another condition in a _or_ and _and_ block of conditions +What a given condition has in its output, can be seen in the openapi spec, by finding the `..out` component. **NOTE** Every condition, has a list of files where the incidents occurred, and the output for a condition is in the extras section. + Example: ```yaml @@ -294,7 +296,7 @@ when: or: - builtin.xml: xpath: "//dependencies/dependency" - filepaths: "{{poms.filepaths}}" + filepaths: "{{poms.extras.filepaths}}" from: poms - builtin.file: pattern: pom.xml diff --git a/provider/internal/builtin/provider.go b/provider/internal/builtin/provider.go index d67a5255..daf291b6 100644 --- a/provider/internal/builtin/provider.go +++ b/provider/internal/builtin/provider.go @@ -99,7 +99,7 @@ func (p *builtinProvider) Capabilities() []provider.Capability { caps = append(caps, filecontentCap) } - fileCap, err := provider.ToProviderCap(r, p.log, fileCondition{}, "file") + fileCap, err := provider.ToProviderInputOutputCap(r, p.log, fileCondition{}, fileTemplateContext{}, "file") if err != nil { p.log.Error(err, "unable to get file capability") } else { diff --git a/provider/internal/builtin/service_client.go b/provider/internal/builtin/service_client.go index 64eeaa65..1019bb8c 100644 --- a/provider/internal/builtin/service_client.go +++ b/provider/internal/builtin/service_client.go @@ -32,6 +32,10 @@ type builtinServiceClient struct { locationCache map[string]float64 } +type fileTemplateContext struct { + Filepaths []string `json:"filepaths,omitempty"` +} + var _ provider.ServiceClient = &builtinServiceClient{} func (p *builtinServiceClient) Stop() {} @@ -147,7 +151,7 @@ func (p *builtinServiceClient) Evaluate(ctx context.Context, cap string, conditi if query == nil || err != nil { return response, fmt.Errorf("could not parse provided xpath query '%s': %v", cond.XML.XPath, err) } - xmlFiles, err := findXMLFiles(p.config.Location, cond.XMLPublicID.Filepaths) + xmlFiles, err := findXMLFiles(p.config.Location, cond.XML.Filepaths) if err != nil { return response, fmt.Errorf("unable to find XML files: %v", err) } diff --git a/provider/provider.go b/provider/provider.go index a4aa091f..7a9d080b 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -846,19 +846,38 @@ func deduplicateDependencies(dependencies map[uri.URI][]*Dep) map[uri.URI][]*Dep return deduped } -func ToProviderCap(r *openapi3.Reflector, log logr.Logger, cond interface{}, name string) (Capability, error) { - jsonCondition, err := r.Reflector.Reflect(cond) +func ToProviderCap(r *openapi3.Reflector, log logr.Logger, input interface{}, name string) (Capability, error) { + jsonCondition, err := r.Reflector.Reflect(input) if err != nil { log.Error(err, "fix it") return Capability{}, err } - s := &openapi3.SchemaOrRef{} - s.FromJSONSchema(jsonschema.SchemaOrBool{ + inputSchemaOrRef := &openapi3.SchemaOrRef{} + inputSchemaOrRef.FromJSONSchema(jsonschema.SchemaOrBool{ TypeObject: &jsonCondition, }) return Capability{ Name: name, - Input: *s, + Input: *inputSchemaOrRef, }, nil } + +func ToProviderInputOutputCap(r *openapi3.Reflector, log logr.Logger, input, output interface{}, name string) (Capability, error) { + cap, err := ToProviderCap(r, log, input, name) + if err != nil { + return cap, err + } + jsonCondition, err := r.Reflector.Reflect(output) + if err != nil { + log.Error(err, "fix it") + return Capability{}, err + } + outputSchemaOrRef := &openapi3.SchemaOrRef{} + outputSchemaOrRef.FromJSONSchema(jsonschema.SchemaOrBool{ + TypeObject: &jsonCondition, + }) + cap.Output = *outputSchemaOrRef + return cap, nil + +} diff --git a/rule-example.yaml b/rule-example.yaml index 15c2ed85..9708fe02 100644 --- a/rule-example.yaml +++ b/rule-example.yaml @@ -29,7 +29,7 @@ or: - builtin.xml: xpath: "//dependencies/dependency" - filepaths: "{{poms.filepaths}}" + filepaths: "{{poms.extras.filepaths}}" from: poms - builtin.file: pattern: pom.xml