Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
aecf519
Add Elastic Agent conditions to manifest specification
teresaromero Oct 15, 2025
4770a5c
Add validation for minimum agent version condition in manifest
teresaromero Oct 16, 2025
19e1259
Add minimum agent version validation to package specifications
teresaromero Oct 16, 2025
5418745
Add validation for agent version definition in package manifest
teresaromero Oct 16, 2025
0d42370
Add support for integration types in minimum agent version validation
teresaromero Oct 16, 2025
88c8ce5
Add comments to clarify the purpose of ValidateMinimumAgentVersion fu…
teresaromero Oct 16, 2025
21c7c22
Reorder import statements in validate_agent_version_required_test.go
teresaromero Oct 16, 2025
45bed14
Update agent version validation and manifest specifications
teresaromero Oct 17, 2025
c631173
Rename file removing required
teresaromero Oct 17, 2025
663d681
Patch integration manifest to remove required before 3.6 and ref only…
teresaromero Oct 17, 2025
cf21ece
Add a newline in import section of validate_agent_version.go for bett…
teresaromero Oct 17, 2025
c7738d4
Refactor agent version validation logic for clarity
teresaromero Oct 20, 2025
64d90f2
Remove unnecessary types specification from ValidateMinimumAgentVersi…
teresaromero Oct 20, 2025
a86c664
Remove conditions requirement from package manifest for compatibility
teresaromero Oct 20, 2025
2e8f570
Remove conditions requirement from package manifest for compatibility
teresaromero Oct 20, 2025
49363fe
Update changelog to require agent version constraints in input and in…
teresaromero Oct 20, 2025
18633cc
Merge branch 'main' into 970-new-agent-version-condition
teresaromero Oct 23, 2025
d35f37d
Add failing test case for agent validation
teresaromero Oct 23, 2025
a9b27d2
Update error message for agent version validation and add missing age…
teresaromero Oct 23, 2025
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
59 changes: 59 additions & 0 deletions code/go/internal/validator/semantic/validate_agent_version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package semantic

import (
"errors"
"fmt"

"github.com/Masterminds/semver/v3"

"github.com/elastic/package-spec/v3/code/go/internal/fspath"
"github.com/elastic/package-spec/v3/code/go/internal/pkgpath"
"github.com/elastic/package-spec/v3/code/go/pkg/specerrors"
)

var (
errInvalidAgentVersionCondition = fmt.Errorf("invalid agent.version condition")
errAgentVersionIncorrectType = fmt.Errorf("manifest agent version is not a string")
)

// ValidateMinimumAgentVersion checks that the package manifest includes the agent.version condition.
func ValidateMinimumAgentVersion(fsys fspath.FS) specerrors.ValidationErrors {
manifest, err := readManifest(fsys)
if err != nil {
return specerrors.ValidationErrors{specerrors.NewStructuredError(err, specerrors.UnassignedCode)}
}

agentVersionCondition, err := getAgentVersionCondition(*manifest)
if err != nil {
return specerrors.ValidationErrors{specerrors.NewStructuredError(err, specerrors.UnassignedCode)}
}

if agentVersionCondition != "" {
if _, err := semver.NewConstraint(agentVersionCondition); err != nil {
return specerrors.ValidationErrors{specerrors.NewStructuredError(errors.Join(err, errInvalidAgentVersionCondition), specerrors.UnassignedCode)}
}
}

return nil
}

func getAgentVersionCondition(manifest pkgpath.File) (string, error) {
val, err := manifest.Values("$.conditions[\"agent.version\"]")
if err != nil {
val, err = manifest.Values("$.conditions.agent.version")
if err != nil {
return "", nil
}
}

sVal, ok := val.(string)
if !ok {
return "", errAgentVersionIncorrectType
}

return sVal, nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package semantic

import (
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/require"

"github.com/elastic/package-spec/v3/code/go/internal/fspath"
)

func TestValidateMinimumAgentVersion(t *testing.T) {
cases := []struct {
title string
manifestYAML string
expectedErr error
}{
{
title: "valid - agent.version condition is present",
manifestYAML: `
name: test-package
version: 1.0.0
conditions:
agent:
version: "^8.0.0"
`,
expectedErr: nil,
},
{
title: "invalid - agent.version condition is missing",
manifestYAML: `
name: test-package
version: 1.0.0
conditions:
some.other.condition: "value"
`,
expectedErr: nil,
},
{
title: "invalid - agent.version condition is not a string",
manifestYAML: `
name: test-package
version: 1.0.0
conditions:
agent.version:
min: "^8.0.0"
`,
expectedErr: errAgentVersionIncorrectType,
},
{
title: "invalid - agent.version condition is not a constraint",
manifestYAML: `
name: test-package
version: 1.0.0
conditions:
agent.version: test
`,
expectedErr: errInvalidAgentVersionCondition,
},
}

for _, c := range cases {
t.Run(c.title, func(t *testing.T) {
tempDir := t.TempDir()

manifestPath := filepath.Join(tempDir, "manifest.yml")
err := os.WriteFile(manifestPath, []byte(c.manifestYAML), 0644)
require.NoError(t, err)

fsys := fspath.DirFS(tempDir)
errs := ValidateMinimumAgentVersion(fsys)

if c.expectedErr != nil {
require.Len(t, errs, 1)
require.ErrorIs(t, errs[0], c.expectedErr)
} else {
require.Empty(t, errs)
}
})
}

}
1 change: 1 addition & 0 deletions code/go/internal/validator/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ func (s Spec) rules(pkgType string, rootSpec spectypes.ItemSpec) validationRules
{fn: semantic.ValidateDeploymentModes, types: []string{"integration"}},
{fn: semantic.ValidateDurationVariables, since: semver.MustParse("3.5.0")},
{fn: semantic.ValidateInputPackagesPolicyTemplates, types: []string{"input"}},
{fn: semantic.ValidateMinimumAgentVersion},
}

var validationRules validationRules
Expand Down
6 changes: 6 additions & 0 deletions code/go/pkg/validator/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,12 @@ func TestValidateFile(t *testing.T) {
"policy template \"sql_query\" references template_path \"\": template_path is required for input type packages",
},
},
"bad_agent_version_v3": {
"manifest.yml",
[]string{
"field conditions.agent: version is required",
},
},
}

for pkgName, test := range tests {
Expand Down
6 changes: 6 additions & 0 deletions spec/changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
- description: Add support for semantic_text field definition.
type: enhancement
link: https://github.com/elastic/package-spec/pull/807
- description: Require defining agent version constraints in input and integration packages.
type: breaking-change
link: https://github.com/elastic/package-spec/pull/999
- version: 3.5.1-next
changes:
- description: Input packages don't require to define fields.
Expand All @@ -23,6 +26,9 @@
- description: Input packages require to define template_path in manifest.
type: enhancement
link: https://github.com/elastic/package-spec/pull/1000
- description: Allow to define agent version constrains in input and integration packages.
type: enhancement
link: https://github.com/elastic/package-spec/pull/999
- version: 3.5.0
changes:
- description: Add `duration` variable data type with `min_duration` and `max_duration` validation properties.
Expand Down
9 changes: 8 additions & 1 deletion spec/content/manifest.spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,14 @@ spec:
categories:
$ref: "../integration/manifest.spec.yml#/definitions/categories"
conditions:
$ref: "../integration/manifest.spec.yml#/definitions/conditions"
description: Conditions under which this package can be installed.
type: object
additionalProperties: false
properties:
elastic:
$ref: "../integration/manifest.spec.yml#/definitions/conditions/properties/elastic"
kibana:
$ref: "../integration/manifest.spec.yml#/definitions/conditions/properties/kibana"
discovery:
$ref: "#/definitions/discovery"
icons:
Expand Down
5 changes: 5 additions & 0 deletions spec/input/manifest.spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,14 @@ spec:
- version
- type
- owner
- conditions

# JSON patches for newer versions should be placed on top
versions:
- before: 3.6.0
patch:
- op: remove
path: "/required/7" # removes requirement for conditions
# Reserve otelcol input name before 3.5.0.
- before: 3.5.0
patch:
Expand Down
23 changes: 23 additions & 0 deletions spec/integration/manifest.spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,20 @@ spec:
description: Kibana versions compatible with this package.
examples:
- ">=7.9.0"
agent:
description: Elastic Agent conditions
type: object
additionalProperties: false
properties:
version:
type: string
description: Elastic Agent versions compatible with this package.
examples:
- "^9.5.0"
required:
- version
required:
- agent
description:
description: >
A longer description of the package. It should describe, at least all the kinds of
Expand Down Expand Up @@ -670,6 +684,7 @@ spec:
- version
- type
- owner
- conditions
allOf:
- if:
properties:
Expand All @@ -692,6 +707,14 @@ spec:

# JSON patches for newer versions should be placed on top
versions:
- before: 3.6.0
patch:
- op: remove
path: "/required/7" # removes requirement for conditions
- op: remove
path: "/definitions/conditions/required/0" # removes requirement for agent
- op: remove
path: "/definitions/conditions/properties/agent/required/0" # removes requirement for version
- before: 3.3.2
patch:
- op: remove
Expand Down
Loading