Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 12 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
51 changes: 51 additions & 0 deletions docs/data-sources/deployment_freezes.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,29 @@ description: |-

Provides information about deployment freezes

## Example Usage

```terraform
data "octopusdeploy_deployment_freezes" "test_freeze" {
ids = null
partial_name = "Freeze Name"
skip = 5
take = 100
}


data "octopusdeploy_deployment_freezes" "project_freezes" {
project_ids = ["projects-1"]
skip = 0
take = 5
}

data "octopusdeploy_deployment_freezes" "tenant_freezes" {
tenant_ids = ["tenants-1"]
skip = 0
take = 10
}
```

<!-- schema generated by tfplugindocs -->
## Schema
Expand All @@ -25,6 +47,7 @@ Provides information about deployment freezes
- `skip` (Number) A filter to specify the number of items to skip in the response.
- `status` (String) Filter by the status of the deployment freeze, value values are Expired, Active, Scheduled (case-insensitive)
- `take` (Number) A filter to specify the number of items to take (or return) in the response.
- `tenant_ids` (List of String) A filter to search by a list of tenant IDs

### Read-Only

Expand All @@ -40,6 +63,34 @@ Read-Only:
- `id` (String) The unique ID for this resource.
- `name` (String) The name of this resource.
- `project_environment_scope` (Map of List of String) The project environment scope of the deployment freeze
- `recurring_schedule` (Attributes) (see [below for nested schema](#nestedatt--deployment_freezes--recurring_schedule))
- `start` (String) The start time of the freeze
- `tenant_project_environment_scope` (Attributes List) The tenant project environment scope of the deployment freeze (see [below for nested schema](#nestedatt--deployment_freezes--tenant_project_environment_scope))

<a id="nestedatt--deployment_freezes--recurring_schedule"></a>
### Nested Schema for `deployment_freezes.recurring_schedule`

Read-Only:

- `date_of_month` (String) The date of the month for monthly schedules
- `day_number_of_month` (String) The day number of the month for monthly schedules
- `day_of_week` (String) The day of the week for monthly schedules
- `days_of_week` (List of String) List of days of the week for weekly schedules
- `end_after_occurrences` (Number) Number of occurrences after which the schedule should end
- `end_on_date` (String) The date when the recurring schedule should end
- `end_type` (String) When the recurring schedule should end (Never, OnDate, AfterOccurrences)
- `monthly_schedule_type` (String) Type of monthly schedule (DayOfMonth, DateOfMonth)
- `type` (String) Type of recurring schedule (OnceDaily, DaysPerWeek, DaysPerMonth, Annually)
- `unit` (Number) The unit value for the schedule


<a id="nestedatt--deployment_freezes--tenant_project_environment_scope"></a>
### Nested Schema for `deployment_freezes.tenant_project_environment_scope`

Read-Only:

- `environment_id` (String) The environment ID
- `project_id` (String) The project ID
- `tenant_id` (String) The tenant ID


35 changes: 35 additions & 0 deletions docs/resources/deployment_freeze.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ resource "octopusdeploy_deployment_freeze" "freeze" {
end = "2024-12-27T00:00:00+08:00"
}

# Freeze recurring freeze yearly on Xmas
resource "octopusdeploy_deployment_freeze" "freeze" {
name = "Xmas"
start = "2024-12-25T00:00:00+10:00"
end = "2024-12-27T00:00:00+08:00"
recurring_schedule = {
type = "Annually"
unit = 1
end_type = "Never"
}
}

resource "octopusdeploy_deployment_freeze_project" "project_freeze" {
deploymentfreeze_id= octopusdeploy_deployment_freeze.freeze.id
project_id = "Projects-123"
Expand Down Expand Up @@ -69,8 +81,31 @@ resource "octopusdeploy_deployment_freeze_tenant" "tenant_freeze" {
- `name` (String) The name of this resource.
- `start` (String) The start time of the freeze, must be RFC3339 format

### Optional

- `recurring_schedule` (Attributes) (see [below for nested schema](#nestedatt--recurring_schedule))

### Read-Only

- `id` (String) The unique ID for this resource.

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

Required:

- `end_type` (String) When the recurring schedule should end (Never, OnDate, AfterOccurrences)
- `type` (String) Type of recurring schedule (OnceDaily, DaysPerWeek, DaysPerMonth, Annually)
- `unit` (Number) The unit value for the schedule

Optional:

- `date_of_month` (String) The date of the month for monthly schedules
- `day_number_of_month` (String) The day number of the month for monthly schedules
- `day_of_week` (String) The day of the week for monthly schedules
- `days_of_week` (List of String) List of days of the week for weekly schedules. Must follow order: Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
- `end_after_occurrences` (Number) Number of occurrences after which the schedule should end
- `end_on_date` (String) The date when the recurring schedule should end
- `monthly_schedule_type` (String) Type of monthly schedule (DayOfMonth, DateOfMonth)


Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
data "octopusdeploy_deployment_freezes" "test_freeze" {
ids = null
partial_name = "Freeze Name"
skip = 5
take = 100
}


data "octopusdeploy_deployment_freezes" "project_freezes" {
project_ids = ["projects-1"]
skip = 0
take = 5
}

data "octopusdeploy_deployment_freezes" "tenant_freezes" {
tenant_ids = ["tenants-1"]
skip = 0
take = 10
}
12 changes: 12 additions & 0 deletions examples/resources/octopusdeploy_deployment_freeze/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@ resource "octopusdeploy_deployment_freeze" "freeze" {
end = "2024-12-27T00:00:00+08:00"
}

# Freeze recurring freeze yearly on Xmas
resource "octopusdeploy_deployment_freeze" "freeze" {
name = "Xmas"
start = "2024-12-25T00:00:00+10:00"
end = "2024-12-27T00:00:00+08:00"
recurring_schedule = {
type = "Annually"
unit = 1
end_type = "Never"
}
}

resource "octopusdeploy_deployment_freeze_project" "project_freeze" {
deploymentfreeze_id= octopusdeploy_deployment_freeze.freeze.id
project_id = "Projects-123"
Expand Down
149 changes: 133 additions & 16 deletions octopusdeploy_framework/datasource_deployment_freeze.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ import (

const deploymentFreezeDatasourceName = "deployment_freezes"

type deploymentFreezesModel struct {
type deploymentFreezesDatasourceModel struct {
ID types.String `tfsdk:"id"`
IDs types.List `tfsdk:"ids"`
PartialName types.String `tfsdk:"partial_name"`
ProjectIDs types.List `tfsdk:"project_ids"`
EnvironmentIDs types.List `tfsdk:"environment_ids"`
TenantIDs types.List `tfsdk:"tenant_ids"`
IncludeComplete types.Bool `tfsdk:"include_complete"`
Status types.String `tfsdk:"status"`
Skip types.Int64 `tfsdk:"skip"`
Expand Down Expand Up @@ -48,7 +49,7 @@ func (d *deploymentFreezeDataSource) Schema(ctx context.Context, req datasource.
}

func (d *deploymentFreezeDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data deploymentFreezesModel
var data deploymentFreezesDatasourceModel
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
Expand All @@ -59,6 +60,7 @@ func (d *deploymentFreezeDataSource) Read(ctx context.Context, req datasource.Re
PartialName: data.PartialName.ValueString(),
ProjectIds: util.Ternary(data.ProjectIDs.IsNull(), []string{}, util.ExpandStringList(data.ProjectIDs)),
EnvironmentIds: util.Ternary(data.EnvironmentIDs.IsNull(), []string{}, util.ExpandStringList(data.EnvironmentIDs)),
TenantIds: util.Ternary(data.TenantIDs.IsNull(), []string{}, util.ExpandStringList(data.TenantIDs)),
IncludeComplete: data.IncludeComplete.ValueBool(),
Status: data.Status.ValueString(),
Skip: int(data.Skip.ValueInt64()),
Expand Down Expand Up @@ -92,31 +94,146 @@ var _ datasource.DataSource = &deploymentFreezeDataSource{}
var _ datasource.DataSourceWithConfigure = &deploymentFreezeDataSource{}

func mapFreezeToAttribute(ctx context.Context, freeze deploymentfreezes.DeploymentFreeze) (attr.Value, diag.Diagnostics) {
var diags diag.Diagnostics

projectScopes := make(map[string]attr.Value)
for projectId, environmentScopes := range freeze.ProjectEnvironmentScope {
projectScopes[projectId] = util.FlattenStringList(environmentScopes)
}

scopeType, diags := types.MapValueFrom(ctx, types.ListType{ElemType: types.StringType}, projectScopes)
if diags.HasError() {
scopeType, scopeDiags := types.MapValueFrom(ctx, types.ListType{ElemType: types.StringType}, projectScopes)
if scopeDiags.HasError() {
diags.Append(scopeDiags...)
return nil, diags
}

tenantScopes := make([]attr.Value, 0)
for _, scope := range freeze.TenantProjectEnvironmentScope {
tenantScope, tDiags := types.ObjectValue(tenantScopeObjectType(), map[string]attr.Value{
"tenant_id": types.StringValue(scope.TenantId),
"project_id": types.StringValue(scope.ProjectId),
"environment_id": types.StringValue(scope.EnvironmentId),
})
if tDiags.HasError() {
diags.Append(tDiags...)
return nil, diags
}
tenantScopes = append(tenantScopes, tenantScope)
}

tenantScopesList, tsDiags := types.ListValue(
types.ObjectType{AttrTypes: tenantScopeObjectType()},
tenantScopes,
)
if tsDiags.HasError() {
diags.Append(tsDiags...)
return nil, diags
}

return types.ObjectValueMust(freezeObjectType(), map[string]attr.Value{
"id": types.StringValue(freeze.ID),
"name": types.StringValue(freeze.Name),
"start": types.StringValue(freeze.Start.Format(time.RFC3339)),
"end": types.StringValue(freeze.End.Format(time.RFC3339)),
"project_environment_scope": scopeType,
}), diags
attrs := map[string]attr.Value{
"id": types.StringValue(freeze.ID),
"name": types.StringValue(freeze.Name),
"start": types.StringValue(freeze.Start.Format(time.RFC3339)),
"end": types.StringValue(freeze.End.Format(time.RFC3339)),
"project_environment_scope": scopeType,
"tenant_project_environment_scope": tenantScopesList,
}

if freeze.RecurringSchedule != nil {
daysOfWeek, daysDiags := types.ListValueFrom(ctx, types.StringType, freeze.RecurringSchedule.DaysOfWeek)
if daysDiags.HasError() {
diags.Append(daysDiags...)
return nil, diags
}

endOnDate := types.StringNull()
if freeze.RecurringSchedule.EndOnDate != nil {
endOnDate = types.StringValue(freeze.RecurringSchedule.EndOnDate.Format(time.RFC3339))
}

endAfterOccurrences := types.Int64Null()
if freeze.RecurringSchedule.EndAfterOccurrences != nil {
endAfterOccurrences = types.Int64Value(int64(*freeze.RecurringSchedule.EndAfterOccurrences))
}

monthlyScheduleType := types.StringNull()
if freeze.RecurringSchedule.MonthlyScheduleType != "" {
monthlyScheduleType = types.StringValue(freeze.RecurringSchedule.MonthlyScheduleType)
}

dateOfMonth := types.StringNull()
if freeze.RecurringSchedule.DateOfMonth != nil {
dateOfMonth = types.StringValue(*freeze.RecurringSchedule.DateOfMonth)
}

dayNumberOfMonth := types.StringNull()
if freeze.RecurringSchedule.DayNumberOfMonth != nil {
dayNumberOfMonth = types.StringValue(*freeze.RecurringSchedule.DayNumberOfMonth)
}

dayOfWeek := types.StringNull()
if freeze.RecurringSchedule.DayOfWeek != nil {
dayOfWeek = types.StringValue(*freeze.RecurringSchedule.DayOfWeek)
}

scheduleAttrs := map[string]attr.Value{
"type": types.StringValue(string(freeze.RecurringSchedule.Type)),
"unit": types.Int64Value(int64(freeze.RecurringSchedule.Unit)),
"end_type": types.StringValue(string(freeze.RecurringSchedule.EndType)),
"end_on_date": endOnDate,
"end_after_occurrences": endAfterOccurrences,
"monthly_schedule_type": monthlyScheduleType,
"date_of_month": dateOfMonth,
"day_number_of_month": dayNumberOfMonth,
"days_of_week": daysOfWeek,
"day_of_week": dayOfWeek,
}

recurringSchedule, rsDiags := types.ObjectValue(freezeRecurringScheduleObjectType(), scheduleAttrs)
if rsDiags.HasError() {
diags.Append(rsDiags...)
return nil, diags
}

attrs["recurring_schedule"] = recurringSchedule
} else {
attrs["recurring_schedule"] = types.ObjectNull(freezeRecurringScheduleObjectType())
}

return types.ObjectValueMust(freezeObjectType(), attrs), diags
}

func freezeRecurringScheduleObjectType() map[string]attr.Type {
return map[string]attr.Type{
"type": types.StringType,
"unit": types.Int64Type,
"end_type": types.StringType,
"end_on_date": types.StringType,
"end_after_occurrences": types.Int64Type,
"monthly_schedule_type": types.StringType,
"date_of_month": types.StringType,
"day_number_of_month": types.StringType,
"days_of_week": types.ListType{ElemType: types.StringType},
"day_of_week": types.StringType,
}
}

func tenantScopeObjectType() map[string]attr.Type {
return map[string]attr.Type{
"tenant_id": types.StringType,
"project_id": types.StringType,
"environment_id": types.StringType,
}
}

func freezeObjectType() map[string]attr.Type {
return map[string]attr.Type{
"id": types.StringType,
"name": types.StringType,
"start": types.StringType,
"end": types.StringType,
"project_environment_scope": types.MapType{ElemType: types.ListType{ElemType: types.StringType}},
"id": types.StringType,
"name": types.StringType,
"start": types.StringType,
"end": types.StringType,
"project_environment_scope": types.MapType{ElemType: types.ListType{ElemType: types.StringType}},
"tenant_project_environment_scope": types.ListType{ElemType: types.ObjectType{AttrTypes: tenantScopeObjectType()}},
"recurring_schedule": types.ObjectType{AttrTypes: freezeRecurringScheduleObjectType()},
}
}
Loading
Loading