mirror of https://github.com/databricks/cli.git
Add anyOf props as required and error when required fields are not specified
This commit is contained in:
parent
769d092108
commit
fca4729221
|
@ -73,12 +73,20 @@ func (s *Schema) validateAdditionalProperties(instance map[string]any) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RequiredPropertyMissingError struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err RequiredPropertyMissingError) Error() string {
|
||||||
|
return fmt.Sprintf("no value provided for required property %s", err.Name)
|
||||||
|
}
|
||||||
|
|
||||||
// This function validates that all require properties in the schema have values
|
// This function validates that all require properties in the schema have values
|
||||||
// in the instance.
|
// in the instance.
|
||||||
func (s *Schema) validateRequired(instance map[string]any) error {
|
func (s *Schema) validateRequired(instance map[string]any) error {
|
||||||
for _, name := range s.Required {
|
for _, name := range s.Required {
|
||||||
if _, ok := instance[name]; !ok {
|
if _, ok := instance[name]; !ok {
|
||||||
return fmt.Errorf("no value provided for required property %s", name)
|
return RequiredPropertyMissingError{Name: name}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -127,13 +127,27 @@ func (c *config) skipPrompt(p jsonschema.Property, r *renderer) (bool, error) {
|
||||||
|
|
||||||
// All fields referred to in a SkipPromptIf condition are implicitly made required and
|
// All fields referred to in a SkipPromptIf condition are implicitly made required and
|
||||||
// we diverge from strictly following the JSON schema because it makes the author UX better.
|
// we diverge from strictly following the JSON schema because it makes the author UX better.
|
||||||
var keys []string
|
required := make(map[string]struct{})
|
||||||
for k := range p.Schema.SkipPromptIf.Properties {
|
for _, k := range p.Schema.SkipPromptIf.Required {
|
||||||
keys = append(keys, k)
|
required[k] = struct{}{}
|
||||||
}
|
}
|
||||||
p.Schema.SkipPromptIf.Required = append(keys, p.Schema.SkipPromptIf.Required...)
|
for k := range p.Schema.SkipPromptIf.Properties {
|
||||||
|
required[k] = struct{}{}
|
||||||
|
}
|
||||||
|
for _, schema := range p.Schema.SkipPromptIf.AnyOf {
|
||||||
|
for k := range schema.Properties {
|
||||||
|
required[k] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.Schema.SkipPromptIf.Required = maps.Keys(required)
|
||||||
|
|
||||||
|
// Validate the partial config against skip_prompt_if schema
|
||||||
validationErr := p.Schema.SkipPromptIf.ValidateInstance(c.values)
|
validationErr := p.Schema.SkipPromptIf.ValidateInstance(c.values)
|
||||||
|
|
||||||
|
target := jsonschema.RequiredPropertyMissingError{}
|
||||||
|
if errors.As(validationErr, &target) {
|
||||||
|
return false, fmt.Errorf("property %s is used in skip_prompt_if but has no value assigned", target.Name)
|
||||||
|
}
|
||||||
if validationErr != nil {
|
if validationErr != nil {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -451,8 +451,10 @@ func TestPromptIsSkippedAnyOf(t *testing.T) {
|
||||||
assert.False(t, skip)
|
assert.False(t, skip)
|
||||||
|
|
||||||
// Values do not match skip condition. Prompt should not be skipped.
|
// Values do not match skip condition. Prompt should not be skipped.
|
||||||
c.values["abc"] = "foobar"
|
c.values = map[string]any{
|
||||||
c.values["def"] = 1234
|
"abc": "foobar",
|
||||||
|
"def": 1234,
|
||||||
|
}
|
||||||
skip, err = c.skipPrompt(jsonschema.Property{
|
skip, err = c.skipPrompt(jsonschema.Property{
|
||||||
Name: "xyz",
|
Name: "xyz",
|
||||||
Schema: c.schema.Properties["xyz"],
|
Schema: c.schema.Properties["xyz"],
|
||||||
|
@ -462,19 +464,21 @@ func TestPromptIsSkippedAnyOf(t *testing.T) {
|
||||||
assert.NotContains(t, c.values, "xyz")
|
assert.NotContains(t, c.values, "xyz")
|
||||||
|
|
||||||
// Missing values. Prompt should not be skipped.
|
// Missing values. Prompt should not be skipped.
|
||||||
c.values["abc"] = "foobar"
|
c.values = map[string]any{
|
||||||
skip, err = c.skipPrompt(jsonschema.Property{
|
"abc": "foobar",
|
||||||
|
}
|
||||||
|
_, err = c.skipPrompt(jsonschema.Property{
|
||||||
Name: "xyz",
|
Name: "xyz",
|
||||||
Schema: c.schema.Properties["xyz"],
|
Schema: c.schema.Properties["xyz"],
|
||||||
}, testRenderer())
|
}, testRenderer())
|
||||||
assert.NoError(t, err)
|
assert.ErrorContains(t, err, "property def is used in skip_prompt_if but has no value assigned")
|
||||||
assert.False(t, skip)
|
|
||||||
assert.NotContains(t, c.values, "xyz")
|
|
||||||
|
|
||||||
// Values match skip condition. Prompt should be skipped. Default value should
|
// Values match skip condition. Prompt should be skipped. Default value should
|
||||||
// be assigned to "xyz".
|
// be assigned to "xyz".
|
||||||
c.values["abc"] = "foobar"
|
c.values = map[string]any{
|
||||||
c.values["def"] = 123
|
"abc": "foobar",
|
||||||
|
"def": 123,
|
||||||
|
}
|
||||||
skip, err = c.skipPrompt(jsonschema.Property{
|
skip, err = c.skipPrompt(jsonschema.Property{
|
||||||
Name: "xyz",
|
Name: "xyz",
|
||||||
Schema: c.schema.Properties["xyz"],
|
Schema: c.schema.Properties["xyz"],
|
||||||
|
@ -485,7 +489,10 @@ func TestPromptIsSkippedAnyOf(t *testing.T) {
|
||||||
|
|
||||||
// Values match skip condition. Prompt should be skipped. Default value should
|
// Values match skip condition. Prompt should be skipped. Default value should
|
||||||
// be assigned to "xyz".
|
// be assigned to "xyz".
|
||||||
c.values["abc"] = "barfoo"
|
c.values = map[string]any{
|
||||||
|
"abc": "barfoo",
|
||||||
|
"def": 0,
|
||||||
|
}
|
||||||
skip, err = c.skipPrompt(jsonschema.Property{
|
skip, err = c.skipPrompt(jsonschema.Property{
|
||||||
Name: "xyz",
|
Name: "xyz",
|
||||||
Schema: c.schema.Properties["xyz"],
|
Schema: c.schema.Properties["xyz"],
|
||||||
|
|
Loading…
Reference in New Issue