Skip to content

Commit

Permalink
Add Git protection rules
Browse files Browse the repository at this point in the history
  • Loading branch information
lourens-octopus committed Jul 28, 2024
1 parent 4427886 commit b03623f
Showing 8 changed files with 288 additions and 10 deletions.
21 changes: 21 additions & 0 deletions docs/data-sources/channels.md
Original file line number Diff line number Diff line change
@@ -43,6 +43,8 @@ data "octopusdeploy_channels" "example" {
Read-Only:

- `description` (String) The description of this channel.
- `git_reference_rules` (List of String) List of rules to restrict which Git references can be used with this channel when creating releases for version controlled projects. References must be fully qualified e.g. `refs/heads/main`. Supports glob patten syntax.
- `git_resource_rules` (List of Object) List of rules to restrict which Git resources can be used with this channel when creating releases with external Git resources. Resources must be fully qualified e.g. `refs/heads/main`. Supports glob patten syntax. (see [below for nested schema](#nestedatt--channels--git_resource_rules))
- `id` (String) The unique ID for this resource.
- `is_default` (Boolean) Indicates if this is the default channel for the associated project.
- `lifecycle_id` (String) The lifecycle ID associated with this channel.
@@ -52,6 +54,25 @@ Read-Only:
- `space_id` (String) The space ID associated with this resource.
- `tenant_tags` (List of String) A list of tenant tags associated with this resource.

<a id="nestedatt--channels--git_resource_rules"></a>
### Nested Schema for `channels.git_resource_rules`

Read-Only:

- `git_dependency_actions` (List of Object) (see [below for nested schema](#nestedobjatt--channels--git_resource_rules--git_dependency_actions))
- `id` (String)
- `rules` (List of String)

<a id="nestedobjatt--channels--git_resource_rules--git_dependency_actions"></a>
### Nested Schema for `channels.git_resource_rules.git_dependency_actions`

Read-Only:

- `deployment_action_slug` (String)
- `git_dependency_name` (String)



<a id="nestedatt--channels--rule"></a>
### Nested Schema for `channels.rule`

24 changes: 24 additions & 0 deletions docs/resources/channel.md
Original file line number Diff line number Diff line change
@@ -30,13 +30,37 @@ resource "octopusdeploy_channel" "example" {
### Optional

- `description` (String) The description of this channel.
- `git_reference_rules` (List of String) List of rules to restrict which Git references can be used with this channel when creating releases for version controlled projects. References must be fully qualified e.g. `refs/heads/main`. Supports glob patten syntax.
- `git_resource_rules` (Block List) List of rules to restrict which Git resources can be used with this channel when creating releases with external Git resources. Resources must be fully qualified e.g. `refs/heads/main`. Supports glob patten syntax. (see [below for nested schema](#nestedblock--git_resource_rules))
- `id` (String) The unique ID for this resource.
- `is_default` (Boolean) Indicates if this is the default channel for the associated project.
- `lifecycle_id` (String) The lifecycle ID associated with this channel.
- `rule` (Block List) A list of rules associated with this channel. (see [below for nested schema](#nestedblock--rule))
- `space_id` (String) The space ID associated with this resource.
- `tenant_tags` (List of String) A list of tenant tags associated with this resource.

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

Required:

- `git_dependency_actions` (Block List, Min: 1) (see [below for nested schema](#nestedblock--git_resource_rules--git_dependency_actions))

Optional:

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

<a id="nestedblock--git_resource_rules--git_dependency_actions"></a>
### Nested Schema for `git_resource_rules.git_dependency_actions`

Optional:

- `deployment_action_slug` (String)
- `git_dependency_name` (String)



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

2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ module github.com/OctopusDeploy/terraform-provider-octopusdeploy
go 1.21

require (
github.com/OctopusDeploy/go-octopusdeploy/v2 v2.43.0
github.com/OctopusDeploy/go-octopusdeploy/v2 v2.44.1
github.com/OctopusSolutionsEngineering/OctopusTerraformTestFramework v0.0.0-20240725054341-2848f54d101e
github.com/google/uuid v1.6.0
github.com/gruntwork-io/terratest v0.41.11
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@ github.com/Microsoft/hcsshim v0.11.5 h1:haEcLNpj9Ka1gd3B3tAEs9CpE0c+1IhoL59w/exY
github.com/Microsoft/hcsshim v0.11.5/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA09d4bExKcU=
github.com/OctopusDeploy/go-octopusdeploy/v2 v2.43.0 h1:fYwGBqG88xy3qHp5j1ySCztdqfw2NLfg2yp0N3XcBYg=
github.com/OctopusDeploy/go-octopusdeploy/v2 v2.43.0/go.mod h1:GZmFu6LmN8Yg0tEoZx3ytk9FnaH+84cWm7u5TdWZC6E=
github.com/OctopusDeploy/go-octopusdeploy/v2 v2.44.1/go.mod h1:GZmFu6LmN8Yg0tEoZx3ytk9FnaH+84cWm7u5TdWZC6E=
github.com/OctopusSolutionsEngineering/OctopusTerraformTestFramework v0.0.0-20240725054341-2848f54d101e h1:FIvWa8wNg8IBG5uVhqkKvcBhaxx4TgN7T8/5Ed4VQUE=
github.com/OctopusSolutionsEngineering/OctopusTerraformTestFramework v0.0.0-20240725054341-2848f54d101e/go.mod h1:Oq9KbiRNDBB5jFmrwnrgLX0urIqR/1ptY18TzkqXm7M=
github.com/ProtonMail/go-crypto v1.1.0-alpha.2 h1:bkyFVUP+ROOARdgCiJzNQo2V2kiB97LyUpzH9P6Hrlg=
52 changes: 43 additions & 9 deletions octopusdeploy/schema_channel.go
Original file line number Diff line number Diff line change
@@ -43,6 +43,18 @@ func expandChannel(d *schema.ResourceData) *channels.Channel {
}
}

if v, ok := d.GetOk("git_reference_rules"); ok {
channel.GitReferenceRules = expandArray(v.([]interface{}))
}

if v, ok := d.GetOk("git_resource_rules"); ok {
channelGitResourceRules := v.([]interface{})
for _, channelGitResourceRule := range channelGitResourceRules {
rule := expandChannelGitResourceRules(channelGitResourceRule.(map[string]interface{}))
channel.GitResourceRules = append(channel.GitResourceRules, rule)
}
}

return channel
}

@@ -52,15 +64,17 @@ func flattenChannel(channel *channels.Channel) map[string]interface{} {
}

return map[string]interface{}{
"description": channel.Description,
"id": channel.GetID(),
"is_default": channel.IsDefault,
"lifecycle_id": channel.LifecycleID,
"name": channel.Name,
"project_id": channel.ProjectID,
"rule": flattenChannelRules(channel.Rules),
"space_id": channel.SpaceID,
"tenant_tags": channel.TenantTags,
"description": channel.Description,
"id": channel.GetID(),
"is_default": channel.IsDefault,
"lifecycle_id": channel.LifecycleID,
"name": channel.Name,
"project_id": channel.ProjectID,
"rule": flattenChannelRules(channel.Rules),
"space_id": channel.SpaceID,
"tenant_tags": channel.TenantTags,
"git_reference_rules": flattenArray(channel.GitReferenceRules),
"git_resource_rules": flattenChannelGitResourceRules(channel.GitResourceRules),
}
}

@@ -112,6 +126,18 @@ func getChannelSchema() map[string]*schema.Schema {
},
"space_id": getSpaceIDSchema(),
"tenant_tags": getTenantTagsSchema(),
"git_reference_rules": {
Description: "List of rules to restrict which Git references can be used with this channel when creating releases for version controlled projects. References must be fully qualified e.g. `refs/heads/main`. Supports glob patten syntax.",
Optional: true,
Type: schema.TypeList,
Elem: &schema.Schema{Type: schema.TypeString},
},
"git_resource_rules": {
Description: "List of rules to restrict which Git resources can be used with this channel when creating releases with external Git resources. Resources must be fully qualified e.g. `refs/heads/main`. Supports glob patten syntax.",
Optional: true,
Type: schema.TypeList,
Elem: &schema.Resource{Schema: getChannelGitResourceRuleSchema()},
},
}
}

@@ -131,5 +157,13 @@ func setChannel(ctx context.Context, d *schema.ResourceData, channel *channels.C
return fmt.Errorf("error setting tenant_tags: %s", err)
}

if err := d.Set("git_reference_rules", channel.GitReferenceRules); err != nil {
return fmt.Errorf("error setting git_reference_rules: %s", err)
}

if err := d.Set("git_resource_rules", flattenChannelGitResourceRules(channel.GitResourceRules)); err != nil {
return fmt.Errorf("error setting git_resource_rules: %s", err)
}

return nil
}
51 changes: 51 additions & 0 deletions octopusdeploy/schema_channel_git_resource_rule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package octopusdeploy

import (
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/channels"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func expandChannelGitResourceRules(ChannelGitResourceRule map[string]interface{}) channels.ChannelGitResourceRule {
if len(ChannelGitResourceRule) == 0 {
return channels.ChannelGitResourceRule{}
}

return channels.ChannelGitResourceRule{
Id: ChannelGitResourceRule["id"].(string),
GitDependencyActions: expandDeploymentActionGitDependencies(ChannelGitResourceRule["git_dependency_actions"]),
Rules: ChannelGitResourceRule["rules"].([]string),
}
}

func flattenChannelGitResourceRules(ChannelGitResourceRules []channels.ChannelGitResourceRule) []map[string]interface{} {
if len(ChannelGitResourceRules) == 0 {
return []map[string]interface{}{}
}

var flattenedRules = make([]map[string]interface{}, len(ChannelGitResourceRules))
for key, ChannelGitResourceRule := range ChannelGitResourceRules {
flattenedRules[key] = map[string]interface{}{
"id": ChannelGitResourceRule.Id,
"git_dependency_actions": flattenDeploymentActionGitDependencies(ChannelGitResourceRule.GitDependencyActions),
"rules": ChannelGitResourceRule.Rules,
}
}

return flattenedRules
}

func getChannelGitResourceRuleSchema() map[string]*schema.Schema {
return map[string]*schema.Schema{
"id": getIDSchema(),
"git_dependency_actions": {
Elem: &schema.Resource{Schema: getDeploymentActionGitDependencySchema()},
Required: true,
Type: schema.TypeList,
},
"rules": {
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
Type: schema.TypeList,
},
}
}
51 changes: 51 additions & 0 deletions octopusdeploy/schema_deployment_action_git_dependency.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package octopusdeploy

import (
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/gitdependencies"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func flattenDeploymentActionGitDependencies(deploymentActionGitDependencies []gitdependencies.DeploymentActionGitDependency) []interface{} {
if len(deploymentActionGitDependencies) == 0 {
return nil
}

var flattenedDeploymentActionPackages []interface{}
for _, v := range deploymentActionGitDependencies {
flattenedDeploymentActionPackage := map[string]interface{}{
"deployment_action_slug": v.DeploymentActionSlug,
"git_dependency_name": v.GitDependencyName,
}
flattenedDeploymentActionPackages = append(flattenedDeploymentActionPackages, flattenedDeploymentActionPackage)
}
return flattenedDeploymentActionPackages
}

func expandDeploymentActionGitDependencies(values interface{}) []gitdependencies.DeploymentActionGitDependency {
if values == nil {
return nil
}

var gitDependencies []gitdependencies.DeploymentActionGitDependency
for _, v := range values.([]interface{}) {
flattenedMap := v.(map[string]interface{})
gitDependencies = append(gitDependencies, gitdependencies.DeploymentActionGitDependency{
DeploymentActionSlug: flattenedMap["deployment_action_slug"].(string),
GitDependencyName: flattenedMap["git_dependency_name"].(string),
})
}
return gitDependencies
}

func getDeploymentActionGitDependencySchema() map[string]*schema.Schema {
return map[string]*schema.Schema{
"deployment_action_slug": {
Optional: true,
Type: schema.TypeString,
},
"git_dependency_name": {
Optional: true,
Type: schema.TypeString,
},
}
}
96 changes: 96 additions & 0 deletions octopusdeploy/schema_deployment_action_git_resource_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package octopusdeploy

import (
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/channels"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/gitdependencies"
"reflect"
"testing"
)

func TestExpandChannelGitResourceRules_WithValidData_ReturnsExpectedResult(t *testing.T) {
input := map[string]interface{}{
"id": "rule-1",
"git_dependency_actions": []interface{}{
map[string]interface{}{
"deployment_action_slug": "deploy-action-1",
"git_dependency_name": "",
},
},
"rules": []string{"rule1", "rule2"},
}

expected := channels.ChannelGitResourceRule{
Id: "rule-1",
GitDependencyActions: []gitdependencies.DeploymentActionGitDependency{
{
DeploymentActionSlug: "deploy-action-1",
GitDependencyName: "",
},
},
Rules: []string{"rule1", "rule2"},
}

actual := expandChannelGitResourceRules(input)

if !reflect.DeepEqual(actual, expected) {
t.Errorf("Expected %+v, got %+v", expected, actual)
}
}

func TestExpandChannelGitResourceRules_WithEmptyData_ReturnsEmptyStruct(t *testing.T) {
input := map[string]interface{}{}

expected := channels.ChannelGitResourceRule{}

actual := expandChannelGitResourceRules(input)

if !reflect.DeepEqual(actual, expected) {
t.Errorf("Expected %+v, got %+v", expected, actual)
}
}

func TestFlattenChannelGitResourceRules_WithValidData_ReturnsExpectedMap(t *testing.T) {
input := []channels.ChannelGitResourceRule{
{
Id: "rule-1",
GitDependencyActions: []gitdependencies.DeploymentActionGitDependency{
{
DeploymentActionSlug: "deploy-action-1",
GitDependencyName: "ref-1",
},
},
Rules: []string{"rule1", "rule2"},
},
}

expected := []map[string]interface{}{
{
"id": "rule-1",
"git_dependency_actions": []interface{}{
map[string]interface{}{
"deployment_action_slug": "deploy-action-1",
"git_dependency_name": "ref-1",
},
},
"rules": []string{"rule1", "rule2"},
},
}

actual := flattenChannelGitResourceRules(input)

if !reflect.DeepEqual(actual, expected) {
t.Errorf("Expected %+v, got %+v", expected, actual)
}
}

func TestFlattenChannelGitResourceRules_WithEmptyData_ReturnsEmptySlice(t *testing.T) {
input := []channels.ChannelGitResourceRule{}

expected := []map[string]interface{}{}

actual := flattenChannelGitResourceRules(input)

if !reflect.DeepEqual(actual, expected) {
t.Errorf("Expected %+v, got %+v", expected, actual)
}
}

0 comments on commit b03623f

Please sign in to comment.