Skip to content
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
8 changes: 8 additions & 0 deletions docs/resources/tenant_common_variable.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,19 @@ Manages a tenant common variable in Octopus Deploy.

### Optional

- `scope` (Block List) Sets the scope of the variable. (see [below for nested schema](#nestedblock--scope))
- `space_id` (String) The space ID associated with this Tenant Common Variable.
- `value` (String, Sensitive) The value of the variable.

### Read-Only

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

<a id="nestedblock--scope"></a>
### Nested Schema for `scope`

Optional:

- `environment_ids` (Set of String) A set of environment IDs to scope this variable to.


10 changes: 9 additions & 1 deletion docs/resources/tenant_project_variable.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,28 @@ resource "octopusdeploy_tenant_project_variable" "example" {

### Required

- `environment_id` (String) The ID of the environment.
- `project_id` (String) The ID of the project.
- `template_id` (String) The ID of the variable template.
- `tenant_id` (String) The ID of the tenant.

### Optional

- `environment_id` (String) The ID of the environment. Use scope block for V2 API with multiple environments.
- `scope` (Block List) Sets the scope of the variable. (see [below for nested schema](#nestedblock--scope))
- `space_id` (String) The space ID associated with this Tenant Project Variable.
- `value` (String, Sensitive) The value of the variable.

### Read-Only

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

<a id="nestedblock--scope"></a>
### Nested Schema for `scope`

Optional:

- `environment_ids` (Set of String) A set of environment IDs to scope this variable to.

## Import

Import is supported using the following syntax:
Expand Down
115 changes: 115 additions & 0 deletions octopusdeploy_framework/framework_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,30 @@ func ProtoV6ProviderFactories() map[string]func() (tfprotov6.ProviderServer, err
}
}

func ProtoV6ProviderFactoriesWithFeatureToggleOverrides(overrides map[string]bool) map[string]func() (tfprotov6.ProviderServer, error) {
return map[string]func() (tfprotov6.ProviderServer, error){
"octopusdeploy": func() (tfprotov6.ProviderServer, error) {
ctx := context.Background()

upgradedSdkServer, err := tf5to6server.UpgradeServer(
ctx,
octopusdeploy.Provider().GRPCProvider)
if err != nil {
log.Fatal(err)
}

providers := []func() tfprotov6.ProviderServer{
func() tfprotov6.ProviderServer {
return upgradedSdkServer
},
providerserver.NewProtocol6(newTestOctopusDeployFrameworkProvider(overrides)),
}

return tf6muxserver.NewMuxServer(context.Background(), providers...)
},
}
}

func TestAccPreCheck(t *testing.T) {
if v := os.Getenv("OCTOPUS_URL"); isEmpty(v) {
t.Fatal("OCTOPUS_URL must be set for acceptance tests")
Expand All @@ -53,3 +77,94 @@ func TestAccPreCheck(t *testing.T) {
func isEmpty(s string) bool {
return len(strings.TrimSpace(s)) == 0
}

func TestTestProviderFeatureToggleOverrides(t *testing.T) {
tests := []struct {
name string
overrides map[string]bool
existingToggles map[string]bool
expectedToggles map[string]bool
description string
}{
{
name: "No overrides",
overrides: map[string]bool{},
existingToggles: map[string]bool{
"SomeFeatureToggle": true,
"SomeOtherFeatureToggle": true,
},
expectedToggles: map[string]bool{
"SomeFeatureToggle": true,
"SomeOtherFeatureToggle": true,
},
description: "No overrides should preserve all toggles",
},
{
name: "Single override",
overrides: map[string]bool{
"FeatureToggleToOverride": false,
},
existingToggles: map[string]bool{
"FeatureToggleToOverride": true,
"SomeOtherFeatureToggle": true,
},
expectedToggles: map[string]bool{
"FeatureToggleToOverride": false,
"SomeOtherFeatureToggle": true,
},
description: "Should override specified toggle while preserving others",
},
{
name: "Multiple overrides",
overrides: map[string]bool{
"FeatureToggleToOverride": true,
"AnotherFeatureToggleToOverride": true,
},
existingToggles: map[string]bool{
"FeatureToggleToOverride": false,
"AnotherFeatureToggleToOverride": false,
"SomeOtherFeatureToggle": false,
},
expectedToggles: map[string]bool{
"FeatureToggleToOverride": true,
"AnotherFeatureToggleToOverride": true,
"SomeOtherFeatureToggle": false,
},
description: "Should override multiple toggles while preserving others",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Create a config with existing toggles
config := &Config{
FeatureToggles: tt.existingToggles,
}

// Simulate what the test provider does
if tt.overrides != nil {
if config.FeatureToggles == nil {
config.FeatureToggles = make(map[string]bool)
}

for key, value := range tt.overrides {
config.FeatureToggles[key] = value
}
}

// Verify the result
for expectedKey, expectedValue := range tt.expectedToggles {
if actualValue, ok := config.FeatureToggles[expectedKey]; !ok {
t.Errorf("%s: expected toggle %q to exist but it was missing", tt.description, expectedKey)
} else if actualValue != expectedValue {
t.Errorf("%s: toggle %q = %t, want %t", tt.description, expectedKey, actualValue, expectedValue)
}
}

// Verify no extra toggles were added
if len(config.FeatureToggles) != len(tt.expectedToggles) {
t.Errorf("%s: got %d toggles, want %d toggles", tt.description, len(config.FeatureToggles), len(tt.expectedToggles))
}
})
}
}
65 changes: 65 additions & 0 deletions octopusdeploy_framework/framework_provider_test_helper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package octopusdeploy_framework

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/provider"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-log/tflog"
)

type testOctopusDeployFrameworkProvider struct {
*octopusDeployFrameworkProvider
featureToggleOverrides map[string]bool
}

var _ provider.Provider = (*testOctopusDeployFrameworkProvider)(nil)

func newTestOctopusDeployFrameworkProvider(overrides map[string]bool) *testOctopusDeployFrameworkProvider {
return &testOctopusDeployFrameworkProvider{
octopusDeployFrameworkProvider: NewOctopusDeployFrameworkProvider(),
featureToggleOverrides: overrides,
}
}

func (p *testOctopusDeployFrameworkProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) {
p.octopusDeployFrameworkProvider.Metadata(ctx, req, resp)
}

func (p *testOctopusDeployFrameworkProvider) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) {
p.octopusDeployFrameworkProvider.Schema(ctx, req, resp)
}

func (p *testOctopusDeployFrameworkProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
p.octopusDeployFrameworkProvider.Configure(ctx, req, resp)

if p.featureToggleOverrides != nil && !resp.Diagnostics.HasError() {
config, ok := resp.ResourceData.(*Config)
if !ok {
resp.Diagnostics.AddError("Test configuration error", "Failed to cast provider data to Config")
return
}

if config.FeatureToggles == nil {
config.FeatureToggles = make(map[string]bool)
}

for key, value := range p.featureToggleOverrides {
config.FeatureToggles[key] = value
tflog.Debug(ctx, fmt.Sprintf("Test override: feature toggle %s = %t", key, value))
}

resp.ResourceData = config
resp.DataSourceData = config
}
}

func (p *testOctopusDeployFrameworkProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
return p.octopusDeployFrameworkProvider.DataSources(ctx)
}

func (p *testOctopusDeployFrameworkProvider) Resources(ctx context.Context) []func() resource.Resource {
return p.octopusDeployFrameworkProvider.Resources(ctx)
}
Loading
Loading