Skip to content

Commit 82ff4b5

Browse files
authored
Merge pull request #6482 from thaJeztah/28.x_backport_plugin_semverish
[28.x backport] cli-plugins/manager: allow schema-versions <= 2.0.0
2 parents cbeddb1 + 2ed0d99 commit 82ff4b5

File tree

2 files changed

+51
-5
lines changed

2 files changed

+51
-5
lines changed

cli-plugins/manager/candidate_test.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ func TestValidateCandidate(t *testing.T) {
5555
// Either err or invalid may be non-empty, but not both (both can be empty for a good plugin).
5656
err string
5757
invalid string
58+
expVer string
5859
}{
5960
// Invalid cases.
6061
{
@@ -95,12 +96,17 @@ func TestValidateCandidate(t *testing.T) {
9596
{
9697
name: "empty schemaversion",
9798
plugin: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{}`},
98-
invalid: `plugin SchemaVersion "" is not valid`,
99+
invalid: `plugin SchemaVersion version cannot be empty`,
99100
},
100101
{
101102
name: "invalid schemaversion",
102103
plugin: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "xyzzy"}`},
103-
invalid: `plugin SchemaVersion "xyzzy" is not valid`,
104+
invalid: `plugin SchemaVersion "xyzzy" has wrong format: must be <major>.<minor>.<patch>`,
105+
},
106+
{
107+
name: "invalid schemaversion major",
108+
plugin: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "2.0.0"}`},
109+
invalid: `plugin SchemaVersion "2.0.0" is not supported: must be lower than 2.0.0`,
104110
},
105111
{
106112
name: "no vendor",
@@ -117,11 +123,25 @@ func TestValidateCandidate(t *testing.T) {
117123
{
118124
name: "valid",
119125
plugin: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.1.0", "Vendor": "e2e-testing"}`},
126+
expVer: "0.1.0",
120127
},
121128
{
122129
// Including the deprecated "experimental" field should not break processing.
123130
name: "with legacy experimental",
124131
plugin: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.1.0", "Vendor": "e2e-testing", "Experimental": true}`},
132+
expVer: "0.1.0",
133+
},
134+
{
135+
// note that this may not be supported by older CLIs
136+
name: "new minor schema version",
137+
plugin: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.2.0", "Vendor": "e2e-testing"}`},
138+
expVer: "0.2.0",
139+
},
140+
{
141+
// note that this may not be supported by older CLIs
142+
name: "new major schema version",
143+
plugin: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "1.0.0", "Vendor": "e2e-testing"}`},
144+
expVer: "1.0.0",
125145
},
126146
} {
127147
t.Run(tc.name, func(t *testing.T) {
@@ -136,7 +156,7 @@ func TestValidateCandidate(t *testing.T) {
136156
default:
137157
assert.NilError(t, err)
138158
assert.Equal(t, metadata.NamePrefix+p.Name, goodPluginName)
139-
assert.Equal(t, p.SchemaVersion, "0.1.0")
159+
assert.Equal(t, p.SchemaVersion, tc.expVer)
140160
assert.Equal(t, p.Vendor, "e2e-testing")
141161
}
142162
})

cli-plugins/manager/plugin.go

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"os"
1010
"os/exec"
1111
"path/filepath"
12+
"strconv"
1213
"strings"
1314

1415
"github.com/docker/cli/cli-plugins/metadata"
@@ -118,8 +119,8 @@ func newPlugin(c pluginCandidate, cmds []*cobra.Command) (Plugin, error) {
118119
p.Err = wrapAsPluginError(err, "invalid metadata")
119120
return p, nil
120121
}
121-
if p.Metadata.SchemaVersion != "0.1.0" {
122-
p.Err = newPluginError("plugin SchemaVersion %q is not valid, must be 0.1.0", p.Metadata.SchemaVersion)
122+
if err := validateSchemaVersion(p.Metadata.SchemaVersion); err != nil {
123+
p.Err = &pluginError{cause: err}
123124
return p, nil
124125
}
125126
if p.Metadata.Vendor == "" {
@@ -129,6 +130,31 @@ func newPlugin(c pluginCandidate, cmds []*cobra.Command) (Plugin, error) {
129130
return p, nil
130131
}
131132

133+
// validateSchemaVersion validates if the plugin's schemaVersion is supported.
134+
//
135+
// The current schema-version is "0.1.0", but we don't want to break compatibility
136+
// until v2.0.0 of the schema version. Check for the major version to be < 2.0.0.
137+
//
138+
// Note that CLI versions before 28.4.1 may not support these versions as they were
139+
// hard-coded to only accept "0.1.0".
140+
func validateSchemaVersion(version string) error {
141+
if version == "0.1.0" {
142+
return nil
143+
}
144+
if version == "" {
145+
return errors.New("plugin SchemaVersion version cannot be empty")
146+
}
147+
major, _, ok := strings.Cut(version, ".")
148+
majorVersion, err := strconv.Atoi(major)
149+
if !ok || err != nil {
150+
return fmt.Errorf("plugin SchemaVersion %q has wrong format: must be <major>.<minor>.<patch>", version)
151+
}
152+
if majorVersion > 1 {
153+
return fmt.Errorf("plugin SchemaVersion %q is not supported: must be lower than 2.0.0", version)
154+
}
155+
return nil
156+
}
157+
132158
// RunHook executes the plugin's hooks command
133159
// and returns its unprocessed output.
134160
func (p *Plugin) RunHook(ctx context.Context, hookData HookPluginData) ([]byte, error) {

0 commit comments

Comments
 (0)