Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Render in arguments section optional computed properties with default values #290

Merged
merged 2 commits into from
Apr 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions openapi/openapi_spec_resource_schema_definition_property.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,13 @@ func (s *SpecSchemaDefinitionProperty) IsOptionalComputed() bool {
return s.isOptional() && !s.isReadOnly() && s.Computed && s.Default == nil
}

// IsOptionalComputedWithDefault returns true for properties that are optional and a value (known at plan time) is computed by the API
// if the client does not provide a value. In order for a property to be considered optional computed it must meet:
// - The property must be optional, not readOnly (computed) and must have a default value populated
func (s *SpecSchemaDefinitionProperty) IsOptionalComputedWithDefault() bool {
return s.isOptional() && !s.isReadOnly() && s.Computed && s.Default != nil
}

func (s *SpecSchemaDefinitionProperty) terraformType() (schema.ValueType, error) {
switch s.Type {
case TypeString:
Expand Down
73 changes: 73 additions & 0 deletions openapi/openapi_spec_resource_schema_definition_property_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,79 @@ func TestSchemaDefinitionPropertyIsOptionalComputed(t *testing.T) {
})
}

func TestSchemaDefinitionPropertyIsOptionalComputedWithDefault(t *testing.T) {
Convey("Given a property that is optional, not readOnly, is computed and does not have a default value (optional-computed property where value is not known at plan time)", t, func() {
s := &SpecSchemaDefinitionProperty{
Type: TypeString,
Required: false,
ReadOnly: false,
Computed: true,
Default: nil,
}
Convey("When IsOptionalComputedWithDefault method is called", func() {
isOptionalComputedWithDefault := s.IsOptionalComputedWithDefault()
Convey("Then value returned should be true", func() {
So(isOptionalComputedWithDefault, ShouldBeFalse)
})
})
})
Convey("Given a property that is not optional", t, func() {
s := &SpecSchemaDefinitionProperty{
Type: TypeString,
Required: true,
}
Convey("When IsOptionalComputedWithDefault method is called", func() {
isOptionalComputedWithDefault := s.IsOptionalComputedWithDefault()
Convey("Then value returned should be true", func() {
So(isOptionalComputedWithDefault, ShouldBeFalse)
})
})
})
Convey("Given a property that is optional but readOnly", t, func() {
s := &SpecSchemaDefinitionProperty{
Type: TypeString,
Required: false,
ReadOnly: true,
}
Convey("When IsOptionalComputedWithDefault method is called", func() {
isOptionalComputedWithDefault := s.IsOptionalComputedWithDefault()
Convey("Then value returned should be true", func() {
So(isOptionalComputedWithDefault, ShouldBeFalse)
})
})
})
Convey("Given a property that is optional, not readOnly and it's not computed (purely optional use case)", t, func() {
s := &SpecSchemaDefinitionProperty{
Type: TypeString,
Required: false,
ReadOnly: false,
Computed: false,
Default: nil,
}
Convey("When IsOptionalComputedWithDefault method is called", func() {
isOptionalComputedWithDefault := s.IsOptionalComputedWithDefault()
Convey("Then value returned should be true", func() {
So(isOptionalComputedWithDefault, ShouldBeFalse)
})
})
})
Convey("Given a property that is optional, not readOnly, computed and has a default value (optional-computed use case, but as far as terraform is concerned the default will be set on the terraform schema (unless it's a type list which is not supported), making it available at plan time - this is by design in terraform)", t, func() {
s := &SpecSchemaDefinitionProperty{
Type: TypeString,
Required: false,
ReadOnly: false,
Computed: true,
Default: "something",
}
Convey("When IsOptionalComputedWithDefault method is called", func() {
isOptionalComputedWithDefault := s.IsOptionalComputedWithDefault()
Convey("Then value returned should be true", func() {
So(isOptionalComputedWithDefault, ShouldBeTrue)
})
})
})
}

func TestTerraformType(t *testing.T) {
Convey("Given a swagger schema definition that has a property of type string", t, func() {
s := &SpecSchemaDefinitionProperty{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,11 @@ func (t TerraformProviderDocGenerator) resourceSchemaToProperty(specSchemaDefini
ArrayItemsType: string(specSchemaDefinitionProperty.ArrayItemsType),
Required: specSchemaDefinitionProperty.IsRequired(),
Computed: specSchemaDefinitionProperty.Computed,
IsOptionalComputed: specSchemaDefinitionProperty.IsOptionalComputed(),
IsOptionalComputed: specSchemaDefinitionProperty.IsOptionalComputed() || specSchemaDefinitionProperty.IsOptionalComputedWithDefault(),
IsSensitive: specSchemaDefinitionProperty.Sensitive,
IsParent: specSchemaDefinitionProperty.IsParentProperty,
Description: specSchemaDefinitionProperty.Description,
Default: specSchemaDefinitionProperty.Default,
Schema: orderProps(schema),
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -495,8 +495,8 @@ func TestGetDataSourceFilters(t *testing.T) {
Type: openapi.TypeObject,
SpecSchemaDefinition: &openapi.SpecSchemaDefinition{
Properties: openapi.SpecSchemaDefinitionProperties{
{Name: "string_prop2", Type: openapi.TypeString},
{Name: "string_prop3", Type: openapi.TypeString},
{Name: "string_prop2", Type: openapi.TypeString},
{Name: "string_prop1", Type: openapi.TypeString},
},
},
Expand All @@ -510,8 +510,8 @@ func TestGetDataSourceFilters(t *testing.T) {
Computed: true,
IsOptionalComputed: true,
Schema: []Property{
{Name: "string_prop3", Type: "string", Required: false, Computed: true, IsOptionalComputed: true},
{Name: "string_prop1", Type: "string", Required: false, Computed: true, IsOptionalComputed: true},
{Name: "string_prop3", Type: "string", Required: false, Computed: true, IsOptionalComputed: true},
{Name: "string_prop2", Type: "string", Required: false, Computed: true, IsOptionalComputed: true},
},
},
Expand Down Expand Up @@ -626,8 +626,8 @@ func TestGetDataSourceInstances(t *testing.T) {
Computed: true,
IsOptionalComputed: true,
Schema: []Property{
{Name: "string_prop3", Type: "string", Required: false, Computed: true, IsOptionalComputed: true},
{Name: "string_prop1", Type: "string", Required: false, Computed: true, IsOptionalComputed: true},
{Name: "string_prop3", Type: "string", Required: false, Computed: true, IsOptionalComputed: true},
{Name: "string_prop2", Type: "string", Required: false, Computed: true, IsOptionalComputed: true},
},
},
Expand Down Expand Up @@ -741,8 +741,8 @@ func TestGetProviderResources(t *testing.T) {
Required: false,
Computed: false,
Schema: []Property{
{Name: "string_prop3", Type: "string", Required: false, Computed: false},
{Name: "string_prop1", Type: "string", Required: false, Computed: false},
{Name: "string_prop3", Type: "string", Required: false, Computed: false},
{Name: "string_prop2", Type: "string", Required: false, Computed: false},
},
},
Expand Down Expand Up @@ -947,9 +947,9 @@ func TestOrderProps(t *testing.T) {
}
orderedProps := orderProps(inputProps)
expectedProps := []Property{
{Name: "prop2"},
{Name: "prop1"},
{Name: "prop3"},
{Name: "prop1"},
{Name: "prop2"},
}
assert.Equal(t, expectedProps, orderedProps)
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type Property struct {
IsSensitive bool
IsParent bool
Description string
Default interface{}
Schema []Property // This is used to describe the schema for array of objects or object properties
}

Expand All @@ -23,3 +24,8 @@ func (p Property) ContainsComputedSubProperties() bool {
}
return false
}

// DefaultNotNil checks whether the Default value is nil. If the value is populated it returns true, false otherwise
func (p Property) DefaultNotNil() bool {
return p.Default != nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,28 @@ func TestProperty_ContainsComputedSubProperties(t *testing.T) {
assert.Equal(t, tc.expectedResult, result)
}
}

func TestProperty_DefaultNotNil(t *testing.T) {
testCases := []struct {
name string
property Property
expectedResult bool
}{
{
name: "property does not contain a default value",
expectedResult: false,
},
{
name: "property does contain a default value",
property: Property{
Name: "some property with schema (eg: object or array of objects) containing computed props",
Default: "some value",
},
expectedResult: true,
},
}
for _, tc := range testCases {
result := tc.property.DefaultNotNil()
assert.Equal(t, tc.expectedResult, result)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ var ArgumentReferenceTmpl = `{{- define "resource_argument_reference" -}}
{{- $required = "Required" -}}
{{end}}
{{- if or .Required (and (not .Required) (not .Computed)) .IsOptionalComputed -}}
<li>{{if eq .Type "object"}}<span class="wysiwyg-color-red">*</span>{{end}} {{.Name}} [{{.Type}} {{- if eq .Type "list" }} of {{.ArrayItemsType}}s{{- end -}}] {{- if .IsSensitive -}}(<a href="#special_terms_definitions_sensitive_property" target="_self">sensitive</a>){{- end}} - ({{$required}}) {{if .IsParent}}The {{.Name}} that this resource belongs to{{else}}{{.Description}}{{end}}
<li>{{if eq .Type "object"}}<span class="wysiwyg-color-red">*</span>{{end}} {{.Name}} [{{.Type}} {{- if eq .Type "list" }} of {{.ArrayItemsType}}s{{- end -}}] {{- if .IsSensitive -}}(<a href="#special_terms_definitions_sensitive_property" target="_self">sensitive</a>){{- end}} - ({{$required}}) {{if .IsParent}}The {{.Name}} that this resource belongs to{{else}}{{.Description}}{{- if .DefaultNotNil -}}. Default value is: {{.Default}}{{- end -}}{{end}}
{{- if or (eq .Type "object") (eq .ArrayItemsType "object")}}. The following properties compose the object schema
:<ul dir="ltr">
{{- range .Schema}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,36 @@ func TestArgumentReferenceTmpl(t *testing.T) {
property: Property{Name: "optional_computed_prop", Type: "string", Description: "this is an optional computed property", IsOptionalComputed: true},
expectedOutput: "<li> optional_computed_prop [string] - (Optional) this is an optional computed property</li>\n\t",
},
{
name: "optional computed property with default value",
property: Property{Name: "optional_computed_prop", Type: "string", Description: "this is an optional computed property", IsOptionalComputed: true, Default: "some default value"},
expectedOutput: "<li> optional_computed_prop [string] - (Optional) this is an optional computed property. Default value is: some default value</li>\n\t",
},
{
name: "optional computed property int with default value",
property: Property{Name: "optional_computed_prop", Type: "integer", Description: "this is an optional computed property", IsOptionalComputed: true, Default: 26},
expectedOutput: "<li> optional_computed_prop [integer] - (Optional) this is an optional computed property. Default value is: 26</li>\n\t",
},
{
name: "optional computed property bool with default value",
property: Property{Name: "optional_computed_prop", Type: "boolean", Description: "this is an optional computed property", IsOptionalComputed: true, Default: true},
expectedOutput: "<li> optional_computed_prop [boolean] - (Optional) this is an optional computed property. Default value is: true</li>\n\t",
},
{
name: "optional computed property bool with default value false",
property: Property{Name: "optional_computed_prop", Type: "boolean", Description: "this is an optional computed property", IsOptionalComputed: true, Default: false},
expectedOutput: "<li> optional_computed_prop [boolean] - (Optional) this is an optional computed property. Default value is: false</li>\n\t",
},
{
name: "optional computed property float with default value",
property: Property{Name: "optional_computed_prop", Type: "number", Description: "this is an optional computed property", IsOptionalComputed: true, Default: 12.99},
expectedOutput: "<li> optional_computed_prop [number] - (Optional) this is an optional computed property. Default value is: 12.99</li>\n\t",
},
{
name: "optional computed property list with default value",
property: Property{Name: "optional_computed_prop", Type: "list", ArrayItemsType: "string", Description: "this is an optional computed property", IsOptionalComputed: true, Default: []string{}},
expectedOutput: "<li> optional_computed_prop [list of strings] - (Optional) this is an optional computed property. Default value is: []</li>\n\t",
},
{
name: "optional property",
property: Property{Name: "optional_prop", Type: "string", Description: "this is an optional property", Required: false},
Expand Down