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

Fix creating and updating hosted deployments with scaling specs #62

Merged
merged 9 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from 7 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
13 changes: 8 additions & 5 deletions docs/resources/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,24 +171,27 @@ Read-Only:
<a id="nestedatt--scaling_spec"></a>
### Nested Schema for `scaling_spec`

Optional:
Required:

- `hibernation_spec` (Attributes) (see [below for nested schema](#nestedatt--scaling_spec--hibernation_spec))
- `hibernation_spec` (Attributes) Hibernation configuration for the deployment. The deployment will hibernate according to the schedules defined in this configuration. To remove the hibernation configuration, set scaling_spec to null. (see [below for nested schema](#nestedatt--scaling_spec--hibernation_spec))

<a id="nestedatt--scaling_spec--hibernation_spec"></a>
### Nested Schema for `scaling_spec.hibernation_spec`

Optional:

- `override` (Attributes) (see [below for nested schema](#nestedatt--scaling_spec--hibernation_spec--override))
- `schedules` (Attributes Set) (see [below for nested schema](#nestedatt--scaling_spec--hibernation_spec--schedules))
- `override` (Attributes) Hibernation override configuration. Set to null to remove the override. (see [below for nested schema](#nestedatt--scaling_spec--hibernation_spec--override))
- `schedules` (Attributes Set) List of hibernation schedules. Set to null to remove all schedules. (see [below for nested schema](#nestedatt--scaling_spec--hibernation_spec--schedules))

<a id="nestedatt--scaling_spec--hibernation_spec--override"></a>
### Nested Schema for `scaling_spec.hibernation_spec.override`

Optional:
Required:

- `is_hibernating` (Boolean)

Optional:

- `override_until` (String)

Read-Only:
Expand Down
186 changes: 110 additions & 76 deletions internal/provider/models/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,23 +244,13 @@ func (data *DeploymentResource) ReadFromResponse(
data.SchedulerSize = types.StringPointerValue((*string)(deployment.SchedulerSize))
data.IsDevelopmentMode = types.BoolPointerValue(deployment.IsDevelopmentMode)
data.IsHighAvailability = types.BoolPointerValue(deployment.IsHighAvailability)

// Currently, the scaling status and spec are only available in development mode
// However, there is a bug in the API where the scaling status and spec are returned even if the deployment is not in development mode for updated deployments
// This is a workaround to handle the bug until the API is fixed
// Issue here: https://github.com/astronomer/astro/issues/21073
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue is fixed

if deployment.IsDevelopmentMode != nil && *deployment.IsDevelopmentMode {
data.ScalingStatus, diags = ScalingStatusTypesObject(ctx, deployment.ScalingStatus)
if diags.HasError() {
return diags
}
data.ScalingSpec, diags = ScalingSpecTypesObject(ctx, deployment.ScalingSpec)
if diags.HasError() {
return diags
}
} else {
data.ScalingStatus = types.ObjectNull(schemas.ScalingStatusAttributeTypes())
data.ScalingSpec = types.ObjectNull(schemas.ScalingSpecAttributeTypes())
data.ScalingStatus, diags = ScalingStatusTypesObject(ctx, deployment.ScalingStatus)
if diags.HasError() {
return diags
}
data.ScalingSpec, diags = ScalingSpecTypesObject(ctx, deployment.ScalingSpec)
if diags.HasError() {
return diags
}

return nil
Expand Down Expand Up @@ -351,23 +341,13 @@ func (data *DeploymentDataSource) ReadFromResponse(
data.SchedulerSize = types.StringPointerValue((*string)(deployment.SchedulerSize))
data.IsDevelopmentMode = types.BoolPointerValue(deployment.IsDevelopmentMode)
data.IsHighAvailability = types.BoolPointerValue(deployment.IsHighAvailability)

// Currently, the scaling status and spec are only available in development mode
// However, there is a bug in the API where the scaling status and spec are returned even if the deployment is not in development mode for updated deployments
// This is a workaround to handle the bug until the API is fixed
// Issue here: https://github.com/astronomer/astro/issues/21073
if deployment.IsDevelopmentMode != nil && *deployment.IsDevelopmentMode {
data.ScalingStatus, diags = ScalingStatusTypesObject(ctx, deployment.ScalingStatus)
if diags.HasError() {
return diags
}
data.ScalingSpec, diags = ScalingSpecTypesObject(ctx, deployment.ScalingSpec)
if diags.HasError() {
return diags
}
} else {
data.ScalingStatus = types.ObjectNull(schemas.ScalingStatusAttributeTypes())
data.ScalingSpec = types.ObjectNull(schemas.ScalingSpecAttributeTypes())
data.ScalingStatus, diags = ScalingStatusTypesObject(ctx, deployment.ScalingStatus)
if diags.HasError() {
return diags
}
data.ScalingSpec, diags = ScalingSpecTypesObject(ctx, deployment.ScalingSpec)
if diags.HasError() {
return diags
}

return nil
Expand Down Expand Up @@ -459,11 +439,11 @@ func WorkerQueueDataSourceTypesObject(
}

type DeploymentScalingSpec struct {
HibernationSpec HibernationSpec `tfsdk:"hibernation_spec"`
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

had to change it to use types.Object for resource creation since it would error otherwise

HibernationSpec types.Object `tfsdk:"hibernation_spec"`
}

type DeploymentStatus struct {
HibernationStatus HibernationStatus `tfsdk:"hibernation_status"`
HibernationStatus types.Object `tfsdk:"hibernation_status"`
}

type HibernationStatus struct {
Expand All @@ -474,8 +454,8 @@ type HibernationStatus struct {
}

type HibernationSpec struct {
Override HibernationSpecOverride `tfsdk:"override"`
Schedules []HibernationSchedule `tfsdk:"schedules"`
Override types.Object `tfsdk:"override"`
Schedules types.Set `tfsdk:"schedules"`
}

type HibernationSpecOverride struct {
Expand All @@ -491,54 +471,108 @@ type HibernationSchedule struct {
WakeAtCron types.String `tfsdk:"wake_at_cron"`
}

func HibernationStatusTypesObject(
ctx context.Context,
hibernationStatus *platform.DeploymentHibernationStatus,
) (types.Object, diag.Diagnostics) {
if hibernationStatus == nil {
return types.ObjectNull(schemas.HibernationStatusAttributeTypes()), nil
}

obj := HibernationStatus{
IsHibernating: types.BoolValue(hibernationStatus.IsHibernating),
NextEventType: types.StringPointerValue((*string)(hibernationStatus.NextEventType)),
NextEventAt: types.StringPointerValue(hibernationStatus.NextEventAt),
Reason: types.StringPointerValue(hibernationStatus.Reason),
}
return types.ObjectValueFrom(ctx, schemas.HibernationStatusAttributeTypes(), obj)
}

func HibernationOverrideTypesObject(
ctx context.Context,
hibernationOverride *platform.DeploymentHibernationOverride,
) (types.Object, diag.Diagnostics) {
if hibernationOverride == nil {
return types.ObjectNull(schemas.HibernationOverrideAttributeTypes()), nil
}
obj := HibernationSpecOverride{
IsHibernating: types.BoolPointerValue(hibernationOverride.IsHibernating),
IsActive: types.BoolPointerValue(hibernationOverride.IsActive),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick note: IsActive is a property set on the API response, it's not something that can be set on the request.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep! got confused a bit by this sometimes but this is for creating the "Terraform response" similar to other "computed" values we have like updatedAt
In resource_deployment.go, we create the request where isActive is not there

}
if hibernationOverride.OverrideUntil != nil {
obj.OverrideUntil = types.StringValue(hibernationOverride.OverrideUntil.Format(time.RFC3339))
}
return types.ObjectValueFrom(ctx, schemas.HibernationOverrideAttributeTypes(), obj)
}

func HibernationScheduleTypesObject(
ctx context.Context,
schedule platform.DeploymentHibernationSchedule,
) (types.Object, diag.Diagnostics) {
obj := HibernationSchedule{
Description: types.StringPointerValue(schedule.Description),
HibernateAtCron: types.StringValue(schedule.HibernateAtCron),
IsEnabled: types.BoolValue(schedule.IsEnabled),
WakeAtCron: types.StringValue(schedule.WakeAtCron),
}
return types.ObjectValueFrom(ctx, schemas.HibernationScheduleAttributeTypes(), obj)
}

func HibernationSpecTypesObject(
ctx context.Context,
hibernationSpec *platform.DeploymentHibernationSpec,
) (types.Object, diag.Diagnostics) {
if hibernationSpec == nil || (hibernationSpec.Override == nil && hibernationSpec.Schedules == nil) {
return types.ObjectNull(schemas.HibernationSpecAttributeTypes()), nil
}

override, diags := HibernationOverrideTypesObject(ctx, hibernationSpec.Override)
if diags.HasError() {
return types.ObjectNull(schemas.HibernationSpecAttributeTypes()), diags
}
schedules, diags := utils.ObjectSet(ctx, hibernationSpec.Schedules, schemas.HibernationScheduleAttributeTypes(), HibernationScheduleTypesObject)
if diags.HasError() {
return types.ObjectNull(schemas.HibernationSpecAttributeTypes()), diags
}
obj := HibernationSpec{
Override: override,
Schedules: schedules,
}
return types.ObjectValueFrom(ctx, schemas.HibernationSpecAttributeTypes(), obj)
}

func ScalingStatusTypesObject(
ctx context.Context,
scalingStatus *platform.DeploymentScalingStatus,
) (types.Object, diag.Diagnostics) {
if scalingStatus != nil && scalingStatus.HibernationStatus != nil {
obj := DeploymentStatus{
HibernationStatus: HibernationStatus{
IsHibernating: types.BoolValue(scalingStatus.HibernationStatus.IsHibernating),
NextEventType: types.StringPointerValue((*string)(scalingStatus.HibernationStatus.NextEventType)),
NextEventAt: types.StringPointerValue(scalingStatus.HibernationStatus.NextEventAt),
Reason: types.StringPointerValue(scalingStatus.HibernationStatus.Reason),
},
}
return types.ObjectValueFrom(ctx, schemas.ScalingStatusAttributeTypes(), obj)
if scalingStatus == nil {
return types.ObjectNull(schemas.ScalingStatusAttributeTypes()), nil
}

hibernationStatus, diags := HibernationStatusTypesObject(ctx, scalingStatus.HibernationStatus)
if diags.HasError() {
return types.ObjectNull(schemas.ScalingStatusAttributeTypes()), diags
}
return types.ObjectNull(schemas.ScalingStatusAttributeTypes()), nil
obj := DeploymentStatus{
HibernationStatus: hibernationStatus,
}
return types.ObjectValueFrom(ctx, schemas.ScalingStatusAttributeTypes(), obj)
}

func ScalingSpecTypesObject(
ctx context.Context,
scalingSpec *platform.DeploymentScalingSpec,
) (types.Object, diag.Diagnostics) {
if scalingSpec != nil && scalingSpec.HibernationSpec != nil && (scalingSpec.HibernationSpec.Override != nil || scalingSpec.HibernationSpec.Schedules != nil) {
obj := DeploymentScalingSpec{
HibernationSpec: HibernationSpec{},
}
if scalingSpec.HibernationSpec.Override != nil {
obj.HibernationSpec.Override = HibernationSpecOverride{
IsHibernating: types.BoolPointerValue(scalingSpec.HibernationSpec.Override.IsHibernating),
IsActive: types.BoolPointerValue(scalingSpec.HibernationSpec.Override.IsActive),
}
if scalingSpec.HibernationSpec.Override.OverrideUntil != nil {
obj.HibernationSpec.Override.OverrideUntil = types.StringValue(scalingSpec.HibernationSpec.Override.OverrideUntil.Format(time.RFC3339))
}
}
if scalingSpec.HibernationSpec.Schedules != nil {
schedules := make([]HibernationSchedule, 0, len(*scalingSpec.HibernationSpec.Schedules))
for _, schedule := range *scalingSpec.HibernationSpec.Schedules {
schedules = append(schedules, HibernationSchedule{
Description: types.StringPointerValue(schedule.Description),
HibernateAtCron: types.StringValue(schedule.HibernateAtCron),
IsEnabled: types.BoolValue(schedule.IsEnabled),
WakeAtCron: types.StringValue(schedule.WakeAtCron),
})
}
obj.HibernationSpec.Schedules = schedules
}
return types.ObjectValueFrom(ctx, schemas.ScalingSpecAttributeTypes(), obj)
if scalingSpec == nil {
return types.ObjectNull(schemas.ScalingSpecAttributeTypes()), nil
}

hibernationSpec, diags := HibernationSpecTypesObject(ctx, scalingSpec.HibernationSpec)
if diags.HasError() {
return types.ObjectNull(schemas.ScalingSpecAttributeTypes()), diags
}
obj := DeploymentScalingSpec{
HibernationSpec: hibernationSpec,
}
return types.ObjectNull(schemas.ScalingSpecAttributeTypes()), nil
return types.ObjectValueFrom(ctx, schemas.ScalingSpecAttributeTypes(), obj)
}
7 changes: 3 additions & 4 deletions internal/provider/resources/resource_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ func (r *ClusterResource) Create(
return
}

var diags diag.Diagnostics
var createClusterRequest platform.CreateClusterRequest

switch platform.ClusterCloudProvider(data.CloudProvider.ValueString()) {
Expand Down Expand Up @@ -493,7 +492,7 @@ func (r *ClusterResource) ValidateConfig(
}

func validateAwsConfig(ctx context.Context, data *models.ClusterResource) diag.Diagnostics {
var diags diag.Diagnostics
diags := make(diag.Diagnostics, 0)

// Unallowed values
if !data.TenantId.IsNull() {
Expand Down Expand Up @@ -524,7 +523,7 @@ func validateAwsConfig(ctx context.Context, data *models.ClusterResource) diag.D
}

func validateAzureConfig(ctx context.Context, data *models.ClusterResource) diag.Diagnostics {
var diags diag.Diagnostics
diags := make(diag.Diagnostics, 0)

// Unallowed values
if !data.ServicePeeringRange.IsNull() {
Expand All @@ -549,7 +548,7 @@ func validateAzureConfig(ctx context.Context, data *models.ClusterResource) diag
}

func validateGcpConfig(ctx context.Context, data *models.ClusterResource) diag.Diagnostics {
var diags diag.Diagnostics
diags := make(diag.Diagnostics, 0)

// required values
if data.ServicePeeringRange.IsNull() {
Expand Down
Loading
Loading