Skip to content

Commit

Permalink
Update OpenAPI spec and generated code (#61)
Browse files Browse the repository at this point in the history
- Update OpenAPI to 2.7.0 (in-development) spec and update generated
  code for REST client and serialization.
- Process sub-schemas for objects nested within lists and maps
  correctly, by using ListNestedAttribute and MapNestedAttribute.
- Inject timeout correctly for test case that exercises DBA password
  rotation timeout.
  • Loading branch information
adriansuarez authored Sep 12, 2024
1 parent a9a2cc7 commit 5d191ff
Show file tree
Hide file tree
Showing 13 changed files with 2,420 additions and 238 deletions.
1 change: 1 addition & 0 deletions docs/data-sources/backup.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ Read-Only:
- `creation_time` (String) The time that the backup was taken
- `message` (String) Message summarizing the state of the backup
- `ready_to_use` (Boolean) Whether the backup is ready to be used to restore a database
- `retained_as` (List of String) The matching retention cycles by this backup
- `state` (String) The state of the backup:
* `Pending` - The backup is pending completion
* `Succeeded` - The backup completed successfully and is available for use
Expand Down
25 changes: 25 additions & 0 deletions docs/data-sources/backuppolicy.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,23 @@ Read-Only:
- `daily` (Number) The number of daily backups to retain
- `hourly` (Number) The number of hourly backups to retain
- `monthly` (Number) The number of monthly backups to retain
- `settings` (Attributes) (see [below for nested schema](#nestedatt--retention--settings))
- `weekly` (Number) The number of weekly backups to retain
- `yearly` (Number) The number of yearly backups to retain

<a id="nestedatt--retention--settings"></a>
### Nested Schema for `retention.settings`

Read-Only:

- `day_of_week` (String) The day of the week used to promote backup to weekly
- `month` (String) The month of the year used to promote backup to yearly
- `promote_latest_to_daily` (Boolean) Whether to promote the latest backup within the day if multiple backups exist for that day
- `promote_latest_to_hourly` (Boolean) Whether to promote the latest backup within the hour if multiple backups exist for that hour
- `promote_latest_to_monthly` (Boolean) Whether to promote the latest backup within the month if multiple backups exist for that month
- `relative_to_last` (Boolean) Whether to apply the backup rotation scheme relative to the last successful backup instead to the current time



<a id="nestedatt--selector"></a>
### Nested Schema for `selector`
Expand All @@ -75,6 +89,17 @@ Read-Only:

Read-Only:

- `last_missed_backups` (Attributes List) The last database backups that were not scheduled by this policy (see [below for nested schema](#nestedatt--status--last_missed_backups))
- `last_missed_schedule_time` (String) The time that backups were last missed by this policy
- `last_schedule_time` (String) The time that backups were last taken by this policy
- `next_schedule_time` (String) The time that backups are next scheduled by this policy

<a id="nestedatt--status--last_missed_backups"></a>
### Nested Schema for `status.last_missed_backups`

Read-Only:

- `database` (String) The fully-qualified database name for which a backup was missed by this policy
- `message` (String) A human readable message indicating details about the missed backup by this policy
- `missed_time` (String) The time that a backup was missed by this policy
- `reason` (String) A programmatic identifier indicating the reason for missing a backup by this policy
3 changes: 2 additions & 1 deletion docs/data-sources/database.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Read-Only:

- `archive_disk_size` (String) The size of the archive volumes for the database. Can be only updated to increase the volume size.
- `journal_disk_size` (String) The size of the journal volumes for the database. Can be only updated to increase the volume size.
- `product_version` (String) The version/tag of the NuoDB image to use. For available tags, see https://hub.docker.com/r/nuodb/nuodb-ce/tags. If omitted, the database version will be inherited from the project.
- `product_version` (String) The version/tag of the NuoDB image to use. For available tags, see https://hub.docker.com/r/nuodb/nuodb/tags. If omitted, the database version will be inherited from the project.
- `tier_parameters` (Map of String) Opaque parameters supplied to database service tier.


Expand Down Expand Up @@ -86,3 +86,4 @@ Read-Only:
* `Failed` - The database has failed to achieve a usable state
* `Deleting` - The database has been marked for deletion, which is in progress
* `Restoring` - Restore from backup is in progress for this database
* `RotatingCertificates` - TLS certificates rotation is in progress for this database
3 changes: 2 additions & 1 deletion docs/data-sources/project.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Read-Only:

Read-Only:

- `product_version` (String) The version/tag of the NuoDB image to use. For available tags, see https://hub.docker.com/r/nuodb/nuodb-ce/tags. If omitted, the project version will be resolved based on the SLA and cluster configuration.
- `product_version` (String) The version/tag of the NuoDB image to use. For available tags, see https://hub.docker.com/r/nuodb/nuodb/tags. If omitted, the project version will be resolved based on the SLA and cluster configuration.
- `tier_parameters` (Map of String) Opaque parameters supplied to project service tier.


Expand All @@ -72,3 +72,4 @@ Read-Only:
* `Expired` - The project and its databases have expired
* `Failed` - The project has failed to achieve a usable state
* `Deleting` - The project has been marked for deletion, which is in progress
* `RotatingCertificates` - TLS certificates rotation is in progress for this domain
1 change: 1 addition & 0 deletions docs/resources/backup.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ Read-Only:
- `creation_time` (String) The time that the backup was taken
- `message` (String) Message summarizing the state of the backup
- `ready_to_use` (Boolean) Whether the backup is ready to be used to restore a database
- `retained_as` (List of String) The matching retention cycles by this backup
- `state` (String) The state of the backup:
* `Pending` - The backup is pending completion
* `Succeeded` - The backup completed successfully and is available for use
Expand Down
25 changes: 25 additions & 0 deletions docs/resources/backuppolicy.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,19 +106,44 @@ Optional:
- `daily` (Number) The number of daily backups to retain
- `hourly` (Number) The number of hourly backups to retain
- `monthly` (Number) The number of monthly backups to retain
- `settings` (Attributes) (see [below for nested schema](#nestedatt--retention--settings))
- `weekly` (Number) The number of weekly backups to retain
- `yearly` (Number) The number of yearly backups to retain

<a id="nestedatt--retention--settings"></a>
### Nested Schema for `retention.settings`

Optional:

- `day_of_week` (String) The day of the week used to promote backup to weekly
- `month` (String) The month of the year used to promote backup to yearly
- `promote_latest_to_daily` (Boolean) Whether to promote the latest backup within the day if multiple backups exist for that day
- `promote_latest_to_hourly` (Boolean) Whether to promote the latest backup within the hour if multiple backups exist for that hour
- `promote_latest_to_monthly` (Boolean) Whether to promote the latest backup within the month if multiple backups exist for that month
- `relative_to_last` (Boolean) Whether to apply the backup rotation scheme relative to the last successful backup instead to the current time



<a id="nestedatt--status"></a>
### Nested Schema for `status`

Read-Only:

- `last_missed_backups` (Attributes List) The last database backups that were not scheduled by this policy (see [below for nested schema](#nestedatt--status--last_missed_backups))
- `last_missed_schedule_time` (String) The time that backups were last missed by this policy
- `last_schedule_time` (String) The time that backups were last taken by this policy
- `next_schedule_time` (String) The time that backups are next scheduled by this policy

<a id="nestedatt--status--last_missed_backups"></a>
### Nested Schema for `status.last_missed_backups`

Read-Only:

- `database` (String) The fully-qualified database name for which a backup was missed by this policy
- `message` (String) A human readable message indicating details about the missed backup by this policy
- `missed_time` (String) The time that a backup was missed by this policy
- `reason` (String) A programmatic identifier indicating the reason for missing a backup by this policy

## Import

Import is supported using the following syntax:
Expand Down
3 changes: 2 additions & 1 deletion docs/resources/database.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Optional:

- `archive_disk_size` (String) The size of the archive volumes for the database. Can be only updated to increase the volume size.
- `journal_disk_size` (String) The size of the journal volumes for the database. Can be only updated to increase the volume size.
- `product_version` (String) The version/tag of the NuoDB image to use. For available tags, see https://hub.docker.com/r/nuodb/nuodb-ce/tags. If omitted, the database version will be inherited from the project.
- `product_version` (String) The version/tag of the NuoDB image to use. For available tags, see https://hub.docker.com/r/nuodb/nuodb/tags. If omitted, the database version will be inherited from the project.
- `tier_parameters` (Map of String) Opaque parameters supplied to database service tier.


Expand Down Expand Up @@ -111,6 +111,7 @@ Read-Only:
* `Failed` - The database has failed to achieve a usable state
* `Deleting` - The database has been marked for deletion, which is in progress
* `Restoring` - Restore from backup is in progress for this database
* `RotatingCertificates` - TLS certificates rotation is in progress for this database

## Import

Expand Down
3 changes: 2 additions & 1 deletion docs/resources/project.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Optional:

Optional:

- `product_version` (String) The version/tag of the NuoDB image to use. For available tags, see https://hub.docker.com/r/nuodb/nuodb-ce/tags. If omitted, the project version will be resolved based on the SLA and cluster configuration.
- `product_version` (String) The version/tag of the NuoDB image to use. For available tags, see https://hub.docker.com/r/nuodb/nuodb/tags. If omitted, the project version will be resolved based on the SLA and cluster configuration.
- `tier_parameters` (Map of String) Opaque parameters supplied to project service tier.


Expand All @@ -96,6 +96,7 @@ Read-Only:
* `Expired` - The project and its databases have expired
* `Failed` - The project has failed to achieve a usable state
* `Deleting` - The project has been marked for deletion, which is in progress
* `RotatingCertificates` - TLS certificates rotation is in progress for this domain

## Import

Expand Down
90 changes: 71 additions & 19 deletions internal/framework/schemas.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,27 +144,23 @@ func GetStringValidators(oas *openapi3.Schema) []validator.String {
return validators
}

// GetTerraformType returns the primitive type appearing in the supplied schema.
// Types "array" and "object" are ignored and should be handled by using
// ToResourceSchema() or ToDataSourceSchema().
func GetTerraformType(schemaRef *openapi3.SchemaRef) attr.Type {
if schemaRef == nil {
return nil
}
if schemaRef.Value == nil {
return types.ObjectType{}
}
switch schemaRef.Value.Type {
case "array":
return types.ListType{}
case "boolean":
return types.BoolType
case "integer":
return types.Int64Type
case "object":
return types.ObjectType{}
case "string":
return types.StringType
default:
return nil
if schemaRef != nil && schemaRef.Value != nil {
switch schemaRef.Value.Type {
case "boolean":
return types.BoolType
case "integer":
return types.Int64Type
case "number":
return types.NumberType
case "string":
return types.StringType
}
}
return nil
}

func appendNonNil[T any](arr []T, elems ...T) []T {
Expand Down Expand Up @@ -238,6 +234,21 @@ func ToResourceAttribute(oas *openapi3.Schema, required, readOnly bool) (string,
// the Terraform API...
switch oas.Type {
case "array":
// If array contains objects, use ListNestedAttribute to attach nested object schema
if oas.Items.Value != nil && oas.Items.Value.Type == "object" {
return name, &resource.ListNestedAttribute{
Description: oas.Description,
MarkdownDescription: oas.Description,
Required: required,
Optional: optional,
Computed: computed,
Sensitive: sensitive,
PlanModifiers: appendNonNil([]planmodifier.List{}, planmodifier.List(useStateForUnknown), planmodifier.List(requiresReplace)),
NestedObject: resource.NestedAttributeObject{
Attributes: ToResourceSchema(oas.Items.Value, readOnly),
},
}
}
return name, &resource.ListAttribute{
Description: oas.Description,
MarkdownDescription: oas.Description,
Expand Down Expand Up @@ -270,6 +281,21 @@ func ToResourceAttribute(oas *openapi3.Schema, required, readOnly bool) (string,
}
case "object":
if oas.AdditionalProperties.Schema != nil {
// If map values are objects, use MapNestedAttribute to attach nested object schema
if oas.AdditionalProperties.Schema.Value != nil && oas.AdditionalProperties.Schema.Value.Type == "object" {
return name, &resource.MapNestedAttribute{
Description: oas.Description,
MarkdownDescription: oas.Description,
Required: required,
Optional: optional,
Computed: computed,
Sensitive: sensitive,
NestedObject: resource.NestedAttributeObject{
Attributes: ToResourceSchema(oas.AdditionalProperties.Schema.Value, readOnly),
},
PlanModifiers: appendNonNil([]planmodifier.Map{}, planmodifier.Map(useStateForUnknown), planmodifier.Map(requiresReplace)),
}
}
return name, &resource.MapAttribute{
Description: oas.Description,
MarkdownDescription: oas.Description,
Expand Down Expand Up @@ -343,6 +369,19 @@ func ToDataSourceAttribute(oas *openapi3.Schema) (string, datasource.Attribute)
// the Terraform API...
switch oas.Type {
case "array":
// If array contains objects, use ListNestedAttribute to attach nested object schema
if oas.Items.Value != nil && oas.Items.Value.Type == "object" {
return name, &datasource.ListNestedAttribute{
Description: oas.Description,
MarkdownDescription: oas.Description,
Required: required,
Computed: computed,
Sensitive: sensitive,
NestedObject: datasource.NestedAttributeObject{
Attributes: ToDataSourceSchema(oas.Items.Value),
},
}
}
return name, &datasource.ListAttribute{
Description: oas.Description,
MarkdownDescription: oas.Description,
Expand All @@ -369,6 +408,19 @@ func ToDataSourceAttribute(oas *openapi3.Schema) (string, datasource.Attribute)
}
case "object":
if oas.AdditionalProperties.Schema != nil {
// If map values are objects, use MapNestedAttribute to attach nested object schema
if oas.AdditionalProperties.Schema.Value != nil && oas.AdditionalProperties.Schema.Value.Type == "object" {
return name, &datasource.MapNestedAttribute{
Description: oas.Description,
MarkdownDescription: oas.Description,
Required: required,
Computed: computed,
Sensitive: sensitive,
NestedObject: datasource.NestedAttributeObject{
Attributes: ToDataSourceSchema(oas.AdditionalProperties.Schema.Value),
},
}
}
return name, &datasource.MapAttribute{
Description: oas.Description,
MarkdownDescription: oas.Description,
Expand Down
38 changes: 23 additions & 15 deletions internal/provider_test/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1112,30 +1112,38 @@ func TestImmutableAttributeChange(t *testing.T) {
require.Error(t, err)
require.Contains(t, string(out), "Configured DBA password was changed")
})
} else {
} else if CONTAINER_SCHEDULING_ENABLED.IsTrue() {
require.NoError(t, err)
t.Run("dbaPasswordChange", func(t *testing.T) {
// Change DBA password and run `terraform apply`
vars.database.DbaPassword = ptr("updated")
tf.WriteConfigT(t, vars.builder.Build())
out, err := tf.Apply()
// Check that DBA password change succeeded
require.NoError(t, err)
require.Contains(t, string(out), "0 to add, 1 to change, 0 to destroy.")
})
} else {
require.NoError(t, err)
t.Run("dbaPasswordChangeTimeout", func(t *testing.T) {
// Change DBA password and run `terraform apply`
vars.database.DbaPassword = ptr("updated")
// Expect readiness check to fail due to DBA password
// not being updated and specify small timeout
if vars.providerCfg.Timeouts == nil {
vars.providerCfg.Timeouts = map[string]framework.OperationTimeouts{
"database": {
Update: ptr("2s"),
},
}
timeouts := vars.providerCfg.Timeouts
defer func() {
vars.providerCfg.Timeouts = timeouts
}()
vars.providerCfg.Timeouts = map[string]framework.OperationTimeouts{
"database": {
Update: ptr("2s"),
},
}
tf.WriteConfigT(t, vars.builder.Build())
out, err := tf.Apply()
if CONTAINER_SCHEDULING_ENABLED.IsTrue() {
// E2E tests disable readiness check completely
require.NoError(t, err)
} else {
// Check that readiness check failed due to DBA password
require.Error(t, err)
require.Contains(t, string(out), "DBA password for database "+vars.project.Organization+"/"+vars.project.Name+"/db has not been updated")
}
// Check that readiness check failed due to DBA password
require.Error(t, err)
require.Contains(t, string(out), "DBA password for database "+vars.project.Organization+"/"+vars.project.Name+"/db has not been updated")
require.Contains(t, string(out), "0 to add, 1 to change, 0 to destroy.")
})
}
Expand Down
Loading

0 comments on commit 5d191ff

Please sign in to comment.