Skip to content
Merged
1 change: 1 addition & 0 deletions docs/data-sources/environments.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Read-Only:

- `allow_dynamic_infrastructure` (Boolean)
- `description` (String) The description of this environment.
- `environment_tags` (Set of String) A list of environment tags associated with this resource.
- `id` (String) The unique ID for this resource.
- `jira_extension_settings` (Attributes List) Provides extension settings for the Jira integration for this environment. (see [below for nested schema](#nestedatt--environments--jira_extension_settings))
- `jira_service_management_extension_settings` (Attributes List) Provides extension settings for the Jira Service Management (JSM) integration for this environment. (see [below for nested schema](#nestedatt--environments--jira_service_management_extension_settings))
Expand Down
3 changes: 3 additions & 0 deletions docs/data-sources/tag_sets.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Provides information about existing tag sets.

- `ids` (List of String) A filter to search by a list of IDs.
- `partial_name` (String) A filter to search by the partial match of a name.
- `scopes` (List of String) A filter to search by scopes. Valid values are `"Tenant"`, `"Environment"`.
- `skip` (Number) A filter to specify the number of items to skip in the response.
- `space_id` (String) The space ID associated with this resource.
- `take` (Number) A filter to specify the number of items to take (or return) in the response.
Expand All @@ -36,9 +37,11 @@ Read-Only:
- `description` (String) The description of this tag set.
- `id` (String) The unique ID for this resource.
- `name` (String) The name of this resource.
- `scopes` (List of String) The resource scopes this tag set applies to. Valid values are `"Tenant"`, `"Environment"`.
- `sort_order` (Number) The sort order associated with this resource.
- `space_id` (String) The space ID associated with this resource.
- `tags` (Attributes List) The tags associated with this tag set. (see [below for nested schema](#nestedatt--tag_sets--tags))
- `type` (String) The type of this tag set. Valid values are `"SingleSelect"`, `"MultiSelect"`, `"FreeText"`.

<a id="nestedatt--tag_sets--tags"></a>
### Nested Schema for `tag_sets.tags`
Expand Down
2 changes: 2 additions & 0 deletions docs/resources/environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ resource "octopusdeploy_environment" "example" {
description = "An environment for the development team."
name = "Development Environment (OK to Delete)"
use_guided_failure = false
environment_tags = ["TagSet1/Tag"]

jira_extension_settings {
environment_type = "unmapped"
Expand All @@ -44,6 +45,7 @@ resource "octopusdeploy_environment" "example" {

- `allow_dynamic_infrastructure` (Boolean)
- `description` (String) The description of this environment.
- `environment_tags` (Set of String) A list of environment tags associated with this resource.
- `jira_extension_settings` (Block List) Provides extension settings for the Jira integration for this environment. (see [below for nested schema](#nestedblock--jira_extension_settings))
- `jira_service_management_extension_settings` (Block List) Provides extension settings for the Jira Service Management (JSM) integration for this environment. (see [below for nested schema](#nestedblock--jira_service_management_extension_settings))
- `servicenow_extension_settings` (Block List) Provides extension settings for the ServiceNow integration for this environment. (see [below for nested schema](#nestedblock--servicenow_extension_settings))
Expand Down
4 changes: 4 additions & 0 deletions docs/resources/tag_set.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ This resource manages tag sets in Octopus Deploy.
resource "octopusdeploy_tag_set" "example" {
description = "Provides tenants with access to certain early access programs."
name = "Early Access Program (EAP)"
scopes = ["Tenant"]
type = "MultiSelect"
}

# tags are distinct resources and associated with tag sets through tag_set_id
Expand Down Expand Up @@ -43,8 +45,10 @@ resource "octopusdeploy_tag" "beta" {
### Optional

- `description` (String) The description of this tag set.
- `scopes` (List of String) The resource scopes this tag set applies to. Valid values are `"Tenant"`, `"Environment"`.
- `sort_order` (Number) The sort order associated with this resource.
- `space_id` (String) The space ID associated with this resource.
- `type` (String) The type of this tag set. Valid values are `"SingleSelect"`, `"MultiSelect"`, `"FreeText"`.

### Read-Only

Expand Down
1 change: 1 addition & 0 deletions examples/resources/octopusdeploy_environment/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ resource "octopusdeploy_environment" "example" {
description = "An environment for the development team."
name = "Development Environment (OK to Delete)"
use_guided_failure = false
environment_tags = ["TagSet1/Tag"]

jira_extension_settings {
environment_type = "unmapped"
Expand Down
2 changes: 2 additions & 0 deletions examples/resources/octopusdeploy_tag_set/resource.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
resource "octopusdeploy_tag_set" "example" {
description = "Provides tenants with access to certain early access programs."
name = "Early Access Program (EAP)"
scopes = ["Tenant"]
type = "MultiSelect"
}

# tags are distinct resources and associated with tag sets through tag_set_id
Expand Down
9 changes: 9 additions & 0 deletions octopusdeploy_framework/datasource_tag_sets.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func (t *tagSetsDataSource) Read(ctx context.Context, req datasource.ReadRequest
query := tagsets.TagSetsQuery{
IDs: util.GetIds(data.IDs),
PartialName: data.PartialName.ValueString(),
Scopes: util.ExpandStringList(data.Scopes),
Skip: int(data.Skip.ValueInt64()),
Take: int(data.Take.ValueInt64()),
}
Expand Down Expand Up @@ -89,13 +90,21 @@ func flattenTagSets(ctx context.Context, tagSets []*tagsets.TagSet) types.List {
})
}

scopeStrings := make([]string, len(tagSet.Scopes))
for k, scope := range tagSet.Scopes {
scopeStrings[k] = string(scope)
}
scopes, _ := types.ListValueFrom(ctx, types.StringType, scopeStrings)

tfList[i] = types.ObjectValueMust(schemas.GetTagSetAttrTypes(), map[string]attr.Value{
"id": types.StringValue(tagSet.ID),
"name": types.StringValue(tagSet.Name),
"description": types.StringValue(tagSet.Description),
"scopes": scopes,
"sort_order": types.Int64Value(int64(tagSet.SortOrder)),
"space_id": types.StringValue(tagSet.SpaceID),
"tags": types.ListValueMust(types.ObjectType{AttrTypes: schemas.GetTagAttrTypes()}, tags),
"type": types.StringValue(string(tagSet.Type)),
})
}

Expand Down
20 changes: 20 additions & 0 deletions octopusdeploy_framework/resource_environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ func (r *environmentTypeResource) Create(ctx context.Context, req resource.Creat
newEnvironment.AllowDynamicInfrastructure = data.AllowDynamicInfrastructure.ValueBool()
newEnvironment.UseGuidedFailure = data.UseGuidedFailure.ValueBool()
newEnvironment.SortOrder = util.GetNumber(data.SortOrder)

if !data.EnvironmentTags.IsNull() && !data.EnvironmentTags.IsUnknown() {
elements := data.EnvironmentTags.Elements()
environmentTags := make([]string, len(elements))
for i, elem := range elements {
environmentTags[i] = elem.(types.String).ValueString()
}
newEnvironment.EnvironmentTags = environmentTags
}
if len(data.JiraExtensionSettings.Elements()) > 0 {
jiraExtensionSettings := mapJiraExtensionSettings(data.JiraExtensionSettings)
if jiraExtensionSettings != nil {
Expand Down Expand Up @@ -124,6 +133,15 @@ func (r *environmentTypeResource) Update(ctx context.Context, req resource.Updat
updatedEnv.UseGuidedFailure = data.UseGuidedFailure.ValueBool()
updatedEnv.SortOrder = util.GetNumber(data.SortOrder)
updatedEnv.SpaceID = data.SpaceID.ValueString()

if !data.EnvironmentTags.IsNull() && !data.EnvironmentTags.IsUnknown() {
elements := data.EnvironmentTags.Elements()
environmentTags := make([]string, len(elements))
for i, elem := range elements {
environmentTags[i] = elem.(types.String).ValueString()
}
updatedEnv.EnvironmentTags = environmentTags
}
if len(data.JiraExtensionSettings.Elements()) > 0 {
jiraExtensionSettings := mapJiraExtensionSettings(data.JiraExtensionSettings)
if jiraExtensionSettings != nil {
Expand Down Expand Up @@ -180,6 +198,8 @@ func updateEnvironment(ctx context.Context, data *schemas.EnvironmentTypeResourc
data.UseGuidedFailure = types.BoolValue(environment.UseGuidedFailure)
}
data.SortOrder = types.Int64Value(int64(environment.SortOrder))

data.EnvironmentTags, _ = types.SetValueFrom(ctx, types.StringType, environment.EnvironmentTags)
if len(environment.ExtensionSettings) != 0 {
for _, extensionSettings := range environment.ExtensionSettings {
switch extensionSettings.ExtensionID() {
Expand Down
37 changes: 29 additions & 8 deletions octopusdeploy_framework/resource_tag_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ func (r *tagSetResource) Create(ctx context.Context, req resource.CreateRequest,
return
}

tagSet := expandTagSet(plan)
tagSet := expandTagSet(ctx, plan)
createdTagSet, err := tagsets.Add(r.Client, tagSet)
if err != nil {
resp.Diagnostics.AddError("Error creating tag set", err.Error())
return
}

state := flattenTagSet(createdTagSet)
state := flattenTagSet(ctx, createdTagSet)
resp.Diagnostics.Append(resp.State.Set(ctx, state)...)
}

Expand All @@ -67,7 +67,7 @@ func (r *tagSetResource) Read(ctx context.Context, req resource.ReadRequest, res
return
}

newState := flattenTagSet(tagSet)
newState := flattenTagSet(ctx, tagSet)
resp.Diagnostics.Append(resp.State.Set(ctx, newState)...)
}

Expand All @@ -78,14 +78,14 @@ func (r *tagSetResource) Update(ctx context.Context, req resource.UpdateRequest,
return
}

tagSet := expandTagSet(plan)
tagSet := expandTagSet(ctx, plan)
updatedTagSet, err := tagsets.Update(r.Client, tagSet)
if err != nil {
resp.Diagnostics.AddError("Error updating tag set", err.Error())
return
}

state := flattenTagSet(updatedTagSet)
state := flattenTagSet(ctx, updatedTagSet)
resp.Diagnostics.Append(resp.State.Set(ctx, state)...)
}

Expand Down Expand Up @@ -115,11 +115,11 @@ func (r *tagSetResource) ImportState(ctx context.Context, req resource.ImportSta
return
}

state := flattenTagSet(tagSet)
state := flattenTagSet(ctx, tagSet)
resp.Diagnostics.Append(resp.State.Set(ctx, state)...)
}

func expandTagSet(model schemas.TagSetResourceModel) *tagsets.TagSet {
func expandTagSet(ctx context.Context, model schemas.TagSetResourceModel) *tagsets.TagSet {
tagSet := tagsets.NewTagSet(model.Name.ValueString())
tagSet.ID = model.ID.ValueString()
tagSet.Description = model.Description.ValueString()
Expand All @@ -129,15 +129,36 @@ func expandTagSet(model schemas.TagSetResourceModel) *tagsets.TagSet {
tagSet.SortOrder = int32(model.SortOrder.ValueInt64())
}

if !model.Scopes.IsNull() && len(model.Scopes.Elements()) > 0 {
scopes := make([]string, 0, len(model.Scopes.Elements()))
model.Scopes.ElementsAs(ctx, &scopes, false)
tagSet.Scopes = make([]tagsets.TagSetScope, 0, len(scopes))
for _, scope := range scopes {
tagSet.Scopes = append(tagSet.Scopes, tagsets.TagSetScope(scope))
}
}

if !model.Type.IsNull() && model.Type.ValueString() != "" {
tagSet.Type = tagsets.TagSetType(model.Type.ValueString())
}

return tagSet
}

func flattenTagSet(tagSet *tagsets.TagSet) schemas.TagSetResourceModel {
func flattenTagSet(ctx context.Context, tagSet *tagsets.TagSet) schemas.TagSetResourceModel {
scopeStrings := make([]string, len(tagSet.Scopes))
for i, scope := range tagSet.Scopes {
scopeStrings[i] = string(scope)
}
scopes, _ := types.ListValueFrom(ctx, types.StringType, scopeStrings)

model := schemas.TagSetResourceModel{
Name: types.StringValue(tagSet.Name),
Description: types.StringValue(tagSet.Description),
Scopes: scopes,
SortOrder: types.Int64Value(int64(tagSet.SortOrder)),
SpaceID: types.StringValue(tagSet.SpaceID),
Type: types.StringValue(string(tagSet.Type)),
}
model.ID = types.StringValue(tagSet.ID)
return model
Expand Down
35 changes: 34 additions & 1 deletion octopusdeploy_framework/resource_tag_set_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package octopusdeploy_framework

import (
"context"
"fmt"
"regexp"
"github.com/OctopusDeploy/terraform-provider-octopusdeploy/octopusdeploy_framework/schemas"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
Expand Down Expand Up @@ -130,17 +132,48 @@ func TestExpandTagSet(t *testing.T) {
sortOrder := int64(10)
spaceID := "Spaces-1"

ctx := context.Background()

tagSetModel := schemas.TagSetResourceModel{
Name: types.StringValue(name),
Description: types.StringValue(description),
SortOrder: types.Int64Value(sortOrder),
SpaceID: types.StringValue(spaceID),
}

tagSet := expandTagSet(tagSetModel)
tagSet := expandTagSet(ctx, tagSetModel)

require.Equal(t, name, tagSet.Name)
require.Equal(t, description, tagSet.Description)
require.Equal(t, int32(sortOrder), tagSet.SortOrder)
require.Equal(t, spaceID, tagSet.SpaceID)
}

func TestAccTagSetValidation(t *testing.T) {
tagSetName := acctest.RandStringFromCharSet(20, acctest.CharSetAlpha)

resource.Test(t, resource.TestCase{
PreCheck: func() { TestAccPreCheck(t) },
ProtoV6ProviderFactories: ProtoV6ProviderFactories(),
Steps: []resource.TestStep{
{
Config: fmt.Sprintf(`
resource "octopusdeploy_tag_set" "%s" {
name = "%s"
scopes = ["InvalidScope"]
}`, tagSetName, tagSetName),
PlanOnly: true,
ExpectError: regexp.MustCompile("Invalid Attribute Value Match"),
},
{
Config: fmt.Sprintf(`
resource "octopusdeploy_tag_set" "%s" {
name = "%s"
type = "InvalidType"
}`, tagSetName, tagSetName),
PlanOnly: true,
ExpectError: regexp.MustCompile("Invalid Attribute Value Match"),
},
},
})
}
16 changes: 16 additions & 0 deletions octopusdeploy_framework/schemas/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func EnvironmentObjectType() map[string]attr.Type {
EnvironmentSortOrder: types.Int64Type,
EnvironmentUseGuidedFailure: types.BoolType,
"space_id": types.StringType,
"environment_tags": types.SetType{ElemType: types.StringType},
EnvironmentJiraExtensionSettings: types.ListType{
ElemType: types.ObjectType{AttrTypes: JiraExtensionSettingsObjectType()},
},
Expand Down Expand Up @@ -118,6 +119,11 @@ func (e EnvironmentSchema) GetDatasourceSchemaAttributes() map[string]datasource
Computed: true,
},
"space_id": GetSpaceIdDatasourceSchema(EnvironmentResourceDescription, true),
"environment_tags": datasourceSchema.SetAttribute{
Computed: true,
Description: "A list of environment tags associated with this resource.",
ElementType: types.StringType,
},
EnvironmentJiraExtensionSettings: datasourceSchema.ListNestedAttribute{
Description: "Provides extension settings for the Jira integration for this environment.",
Computed: true,
Expand Down Expand Up @@ -183,6 +189,12 @@ func (e EnvironmentSchema) GetResourceSchema() resourceSchema.Schema {
stringplanmodifier.RequiresReplace(),
).
Build(),
"environment_tags": resourceSchema.SetAttribute{
Description: "A list of environment tags associated with this resource.",
ElementType: types.StringType,
Optional: true,
Computed: true,
},
},
Blocks: map[string]resourceSchema.Block{
EnvironmentJiraExtensionSettings: resourceSchema.ListNestedBlock{
Expand Down Expand Up @@ -273,6 +285,9 @@ func MapFromEnvironment(ctx context.Context, environment *environments.Environme
env.AllowDynamicInfrastructure = types.BoolValue(environment.AllowDynamicInfrastructure)
env.SortOrder = types.Int64Value(int64(environment.SortOrder))
env.UseGuidedFailure = types.BoolValue(environment.UseGuidedFailure)

env.EnvironmentTags, _ = types.SetValueFrom(ctx, types.StringType, environment.EnvironmentTags)

env.JiraExtensionSettings, _ = types.ListValueFrom(ctx, types.ObjectType{AttrTypes: JiraExtensionSettingsObjectType()}, []any{})
env.JiraServiceManagementExtensionSettings, _ = types.ListValueFrom(ctx, types.ObjectType{AttrTypes: JiraServiceManagementExtensionSettingsObjectType()}, []any{})
env.ServiceNowExtensionSettings, _ = types.ListValueFrom(ctx, types.ObjectType{AttrTypes: ServiceNowExtensionSettingsObjectType()}, []any{})
Expand Down Expand Up @@ -316,6 +331,7 @@ type EnvironmentTypeResourceModel struct {
SortOrder types.Int64 `tfsdk:"sort_order"`
UseGuidedFailure types.Bool `tfsdk:"use_guided_failure"`
SpaceID types.String `tfsdk:"space_id"`
EnvironmentTags types.Set `tfsdk:"environment_tags"`
JiraExtensionSettings types.List `tfsdk:"jira_extension_settings"`
JiraServiceManagementExtensionSettings types.List `tfsdk:"jira_service_management_extension_settings"`
ServiceNowExtensionSettings types.List `tfsdk:"servicenow_extension_settings"`
Expand Down
1 change: 1 addition & 0 deletions octopusdeploy_framework/schemas/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ var testableSchemas = []EntitySchema{
MavenFeedSchema{},
ProjectGroupSchema{},
TagSchema{},
TagSetSchema{},
UsernamePasswordAccountSchema{},
VariableSchema{},
TenantProjectVariableSchema{},
Expand Down
Loading
Loading