Add AnyOf Support to SkipPromptIf

This commit is contained in:
Arpit Jasapara 2024-01-19 01:21:24 -08:00
parent 7067782cf1
commit 04946d268a
No known key found for this signature in database
GPG Key ID: F10F7691DDA7C0B9
3 changed files with 116 additions and 4 deletions

View File

@ -60,6 +60,9 @@ type Schema struct {
// Extension embeds our custom JSON schema extensions.
Extension
// Schema that must match any of the schemas in the array
AnyOf []*Schema `json:"anyOf,omitempty"`
}
// Default value defined in a JSON Schema, represented as a string.

View File

@ -127,11 +127,34 @@ func (c *config) skipPrompt(p jsonschema.Property, r *renderer) (bool, error) {
// Check if conditions specified by template author for skipping the prompt
// are satisfied. If they are not, we have to prompt for a user input.
for name, property := range p.Schema.SkipPromptIf.Properties {
if v, ok := c.values[name]; ok && v == property.Const {
continue
if p.Schema.SkipPromptIf.Properties != nil {
for name, property := range p.Schema.SkipPromptIf.Properties {
if v, ok := c.values[name]; ok && v == property.Const {
continue
}
return false, nil
}
}
// Check if AnyOf is set first. If so, then iterate over all property sets to find a match.
// If no match is found (allFalse stays true), we have to prompt for a user input.
if p.Schema.SkipPromptIf.AnyOf != nil {
allFalse := true
for _, properties := range p.Schema.SkipPromptIf.AnyOf {
match := true
for name, property := range properties.Properties {
if v, ok := c.values[name]; ok && v == property.Const {
continue
}
match = false
}
if match {
allFalse = false
}
}
if allFalse {
return false, nil
}
return false, nil
}
if p.Schema.Default == nil {

View File

@ -398,3 +398,89 @@ func TestPromptIsSkipped(t *testing.T) {
assert.True(t, skip)
assert.Equal(t, "hello-world", c.values["xyz"])
}
func TestPromptIsSkippedAnyOf(t *testing.T) {
c := config{
ctx: context.Background(),
values: make(map[string]any),
schema: &jsonschema.Schema{
Properties: map[string]*jsonschema.Schema{
"abc": {
Type: "string",
},
"def": {
Type: "integer",
},
"xyz": {
Type: "string",
Default: "hello-world",
Extension: jsonschema.Extension{
SkipPromptIf: &jsonschema.Schema{
AnyOf: []*jsonschema.Schema{
{
Properties: map[string]*jsonschema.Schema{
"abc": {
Const: "foobar",
},
"def": {
Const: 123,
},
},
},
{
Properties: map[string]*jsonschema.Schema{
"abc": {
Const: "barfoo",
},
},
},
},
},
},
},
},
},
}
// No skip condition defined. Prompt should not be skipped.
skip, err := c.skipPrompt(jsonschema.Property{
Name: "abc",
Schema: c.schema.Properties["abc"],
}, testRenderer())
assert.NoError(t, err)
assert.False(t, skip)
// Values do not match skip condition. Prompt should not be skipped.
c.values["abc"] = "foobar"
c.values["def"] = 1234
skip, err = c.skipPrompt(jsonschema.Property{
Name: "xyz",
Schema: c.schema.Properties["xyz"],
}, testRenderer())
assert.NoError(t, err)
assert.False(t, skip)
assert.NotContains(t, c.values, "xyz")
// Values match skip condition. Prompt should be skipped. Default value should
// be assigned to "xyz".
c.values["abc"] = "foobar"
c.values["def"] = 123
skip, err = c.skipPrompt(jsonschema.Property{
Name: "xyz",
Schema: c.schema.Properties["xyz"],
}, testRenderer())
assert.NoError(t, err)
assert.True(t, skip)
assert.Equal(t, "hello-world", c.values["xyz"])
// Values match skip condition. Prompt should be skipped. Default value should
// be assigned to "xyz".
c.values["abc"] = "barfoo"
skip, err = c.skipPrompt(jsonschema.Property{
Name: "xyz",
Schema: c.schema.Properties["xyz"],
}, testRenderer())
assert.NoError(t, err)
assert.True(t, skip)
assert.Equal(t, "hello-world", c.values["xyz"])
}