mirror of https://github.com/databricks/cli.git
Add support for validating CLI version when loading a jsonschema object (#883)
## Changes Updates to bundle templates can require updated versions of the CLI. This PR extends the JSON schema representation to allow template authors to set a min CLI version they require for their templates. This is required to make improvements/additions to the mlops-stacks repo ## Tests Tested using unit tests and manually. For manualy testing, I created a custom build of the CLI using go releaser and then tested it against a local instance of mlops-stack When mlops-stack schema has: ``` "min_databricks_cli_version": "v5000.1.1", ``` output (error as expected) ``` shreyas.goenka@THW32HFW6T bricks % ./dist/cli_darwin_arm64/databricks bundle init ~/mlops-stack Error: minimum CLI version "v5000.1.1" is greater than current CLI version "v0.207.2-dev+1b992c0". Please upgrade your current Databricks CLI ``` When the mlops-stack schema has: ``` "min_databricks_cli_version": "v0.1.1", ``` output (validation passes) ``` shreyas.goenka@THW32HFW6T bricks % ./dist/cli_darwin_arm64/databricks bundle init ~/mlops-stack Welcome to MLOps Stack. For detailed information on project generation, see the README at https://github.com/databricks/mlops-stack/blob/main/README.md. Project Name [my-mlops-project]: ^C ```
This commit is contained in:
parent
7139487c2f
commit
3700785dfa
|
@ -33,6 +33,8 @@ var info Info
|
|||
|
||||
var once sync.Once
|
||||
|
||||
var DefaultSemver = "0.0.0-dev"
|
||||
|
||||
// getDefaultBuildVersion uses build information stored by Go itself
|
||||
// to synthesize a build version if one wasn't set.
|
||||
// This is necessary if the binary was not built through goreleaser.
|
||||
|
@ -47,7 +49,7 @@ func getDefaultBuildVersion() string {
|
|||
m[s.Key] = s.Value
|
||||
}
|
||||
|
||||
out := "0.0.0-dev"
|
||||
out := DefaultSemver
|
||||
|
||||
// Append revision as build metadata.
|
||||
if v, ok := m["vcs.revision"]; ok {
|
||||
|
|
|
@ -18,4 +18,9 @@ type Extension struct {
|
|||
// PatternMatchFailureMessage is a user defined message that is displayed to the
|
||||
// user if a JSON schema pattern match fails.
|
||||
PatternMatchFailureMessage string `json:"pattern_match_failure_message,omitempty"`
|
||||
|
||||
// Set the minimum semver version of this CLI to validate when loading this schema.
|
||||
// If the CLI version is less than this value, then validation for this
|
||||
// schema will fail.
|
||||
MinDatabricksCliVersion string `json:"min_databricks_cli_version,omitempty"`
|
||||
}
|
||||
|
|
|
@ -6,6 +6,9 @@ import (
|
|||
"os"
|
||||
"regexp"
|
||||
"slices"
|
||||
|
||||
"github.com/databricks/cli/internal/build"
|
||||
"golang.org/x/mod/semver"
|
||||
)
|
||||
|
||||
// defines schema for a json object
|
||||
|
@ -67,8 +70,8 @@ const (
|
|||
IntegerType Type = "integer"
|
||||
)
|
||||
|
||||
func (schema *Schema) validate() error {
|
||||
// Validate property types are all valid JSON schema types.
|
||||
func (schema *Schema) validateSchemaPropertyTypes() error {
|
||||
for _, v := range schema.Properties {
|
||||
switch v.Type {
|
||||
case NumberType, BooleanType, StringType, IntegerType:
|
||||
|
@ -83,8 +86,11 @@ func (schema *Schema) validate() error {
|
|||
return fmt.Errorf("type %s is not a recognized json schema type", v.Type)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate default property values are consistent with types.
|
||||
func (schema *Schema) validateSchemaDefaultValueTypes() error {
|
||||
for name, property := range schema.Properties {
|
||||
if property.Default == nil {
|
||||
continue
|
||||
|
@ -93,8 +99,11 @@ func (schema *Schema) validate() error {
|
|||
return fmt.Errorf("type validation for default value of property %s failed: %w", name, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate enum field values for properties are consistent with types.
|
||||
func (schema *Schema) validateSchemaEnumValueTypes() error {
|
||||
for name, property := range schema.Properties {
|
||||
if property.Enum == nil {
|
||||
continue
|
||||
|
@ -106,8 +115,11 @@ func (schema *Schema) validate() error {
|
|||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate default value is contained in the list of enums if both are defined.
|
||||
func (schema *Schema) validateSchemaDefaultValueIsInEnums() error {
|
||||
for name, property := range schema.Properties {
|
||||
if property.Default == nil || property.Enum == nil {
|
||||
continue
|
||||
|
@ -118,8 +130,11 @@ func (schema *Schema) validate() error {
|
|||
return fmt.Errorf("list of enum values for property %s does not contain default value %v: %v", name, property.Default, property.Enum)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate usage of "pattern" is consistent.
|
||||
func (schema *Schema) validateSchemaPattern() error {
|
||||
for name, property := range schema.Properties {
|
||||
pattern := property.Pattern
|
||||
if pattern == "" {
|
||||
|
@ -153,6 +168,47 @@ func (schema *Schema) validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (schema *Schema) validateSchemaMinimumCliVersion(currentVersion string) func() error {
|
||||
return func() error {
|
||||
if schema.MinDatabricksCliVersion == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Ignore this validation rule for local builds.
|
||||
if semver.Compare("v"+build.DefaultSemver, currentVersion) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Confirm that MinDatabricksCliVersion is a valid semver.
|
||||
if !semver.IsValid(schema.MinDatabricksCliVersion) {
|
||||
return fmt.Errorf("invalid minimum CLI version %q specified. Please specify the version in the format v0.0.0", schema.MinDatabricksCliVersion)
|
||||
}
|
||||
|
||||
// Confirm that MinDatabricksCliVersion is less than or equal to the current version.
|
||||
if semver.Compare(schema.MinDatabricksCliVersion, currentVersion) > 0 {
|
||||
return fmt.Errorf("minimum CLI version %q is greater than current CLI version %q. Please upgrade your current Databricks CLI", schema.MinDatabricksCliVersion, currentVersion)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (schema *Schema) validate() error {
|
||||
for _, fn := range []func() error{
|
||||
schema.validateSchemaPropertyTypes,
|
||||
schema.validateSchemaDefaultValueTypes,
|
||||
schema.validateSchemaEnumValueTypes,
|
||||
schema.validateSchemaDefaultValueIsInEnums,
|
||||
schema.validateSchemaPattern,
|
||||
schema.validateSchemaMinimumCliVersion("v" + build.GetInfo().Version),
|
||||
} {
|
||||
err := fn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Load(path string) (*Schema, error) {
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
|
|
|
@ -222,3 +222,42 @@ func TestSchemaValidatePatternEnum(t *testing.T) {
|
|||
}
|
||||
assert.NoError(t, s.validate())
|
||||
}
|
||||
|
||||
func TestValidateSchemaMinimumCliVersionWithInvalidSemver(t *testing.T) {
|
||||
s := &Schema{
|
||||
Extension: Extension{
|
||||
MinDatabricksCliVersion: "1.0.5",
|
||||
},
|
||||
}
|
||||
err := s.validateSchemaMinimumCliVersion("v2.0.1")()
|
||||
assert.ErrorContains(t, err, "invalid minimum CLI version \"1.0.5\" specified. Please specify the version in the format v0.0.0")
|
||||
|
||||
s.MinDatabricksCliVersion = "v1.0.5"
|
||||
err = s.validateSchemaMinimumCliVersion("v2.0.1")()
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestValidateSchemaMinimumCliVersion(t *testing.T) {
|
||||
s := &Schema{
|
||||
Extension: Extension{
|
||||
MinDatabricksCliVersion: "v1.0.5",
|
||||
},
|
||||
}
|
||||
err := s.validateSchemaMinimumCliVersion("v2.0.1")()
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = s.validateSchemaMinimumCliVersion("v1.0.5")()
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = s.validateSchemaMinimumCliVersion("v1.0.6")()
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = s.validateSchemaMinimumCliVersion("v1.0.4")()
|
||||
assert.ErrorContains(t, err, `minimum CLI version "v1.0.5" is greater than current CLI version "v1.0.4". Please upgrade your current Databricks CLI`)
|
||||
|
||||
err = s.validateSchemaMinimumCliVersion("v0.0.1")()
|
||||
assert.ErrorContains(t, err, "minimum CLI version \"v1.0.5\" is greater than current CLI version \"v0.0.1\". Please upgrade your current Databricks CLI")
|
||||
|
||||
err = s.validateSchemaMinimumCliVersion("v0.0.0-dev")()
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue