diff --git a/CHANGELOG.md b/CHANGELOG.md index 31020ba97..bee152721 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Unreleased +## Enhancements + +* Add BETA support for adding custom project permission for variable sets `ProjectVariableSetsPermission` by @netramali [21879](https://github.com/hashicorp/atlas/pull/21879) + # v1.73.1 ## Bug fixes diff --git a/team_project_access.go b/team_project_access.go index a08d0992f..36e9cda8d 100644 --- a/team_project_access.go +++ b/team_project_access.go @@ -71,6 +71,9 @@ type TeamProjectAccess struct { type TeamProjectAccessProjectPermissions struct { ProjectSettingsPermission ProjectSettingsPermissionType `jsonapi:"attr,settings"` ProjectTeamsPermission ProjectTeamsPermissionType `jsonapi:"attr,teams"` + // ProjectVariableSetsPermission represents read, manage, and no access custom permission for project-level variable sets + // This relation is considered BETA, SUBJECT TO CHANGE, and likely unavailable to most users. + ProjectVariableSetsPermission ProjectVariableSetsPermissionType `jsonapi:"attr,variable-sets"` } // WorkspacePermissions represents the team's permission on all workspaces in its project @@ -104,6 +107,16 @@ const ( ProjectTeamsPermissionManage ProjectTeamsPermissionType = "manage" ) +// ProjectVariableSetsPermissionType represents the permission type to a project's variable sets +// This relation is considered BETA, SUBJECT TO CHANGE, and likely unavailable to most users. +type ProjectVariableSetsPermissionType string + +const ( + ProjectVariableSetsPermissionNone ProjectVariableSetsPermissionType = "none" + ProjectVariableSetsPermissionRead ProjectVariableSetsPermissionType = "read" + ProjectVariableSetsPermissionWrite ProjectVariableSetsPermissionType = "write" +) + // WorkspaceRunsPermissionType represents the permissiontype to project workspaces' runs type WorkspaceRunsPermissionType string @@ -143,6 +156,8 @@ const ( type TeamProjectAccessProjectPermissionsOptions struct { Settings *ProjectSettingsPermissionType `json:"settings,omitempty"` Teams *ProjectTeamsPermissionType `json:"teams,omitempty"` + // This relation is considered BETA, SUBJECT TO CHANGE, and likely unavailable to most users. + VariableSets *ProjectVariableSetsPermissionType `json:"variable-sets,omitempty"` } type TeamProjectAccessWorkspacePermissionsOptions struct { diff --git a/team_project_access_integration_test.go b/team_project_access_integration_test.go index 831c1f1c6..9770f6357 100644 --- a/team_project_access_integration_test.go +++ b/team_project_access_integration_test.go @@ -165,6 +165,58 @@ func TestTeamProjectAccessesAdd(t *testing.T) { } }) + t.Run("with no project access options for custom TeamProject permissions", func(t *testing.T) { + skipUnlessBeta(t) + options := TeamProjectAccessAddOptions{ + Access: *ProjectAccess(TeamProjectAccessCustom), + Team: tmTest, + Project: pTest, + ProjectAccess: &TeamProjectAccessProjectPermissionsOptions{}, + WorkspaceAccess: &TeamProjectAccessWorkspacePermissionsOptions{ + Runs: WorkspaceRunsPermission(WorkspaceRunsPermissionApply), + SentinelMocks: WorkspaceSentinelMocksPermission(WorkspaceSentinelMocksPermissionRead), + StateVersions: WorkspaceStateVersionsPermission(WorkspaceStateVersionsPermissionWrite), + Variables: WorkspaceVariablesPermission(WorkspaceVariablesPermissionWrite), + Create: Bool(true), + Locking: Bool(true), + Move: Bool(true), + Delete: Bool(false), + RunTasks: Bool(false), + }, + } + + tpa, err := client.TeamProjectAccess.Add(ctx, options) + defer func() { + err := client.TeamProjectAccess.Remove(ctx, tpa.ID) + if err != nil { + t.Logf("error removing team access (%s): %s", tpa.ID, err) + } + }() + + require.NoError(t, err) + + // Get a refreshed view from the API. + refreshed, err := client.TeamProjectAccess.Read(ctx, tpa.ID) + require.NoError(t, err) + + for _, item := range []*TeamProjectAccess{ + tpa, + refreshed, + } { + assert.NotEmpty(t, item.ID) + assert.Equal(t, options.Access, item.Access) + assert.Equal(t, *options.WorkspaceAccess.Runs, item.WorkspaceAccess.WorkspaceRunsPermission) + assert.Equal(t, *options.WorkspaceAccess.SentinelMocks, item.WorkspaceAccess.WorkspaceSentinelMocksPermission) + assert.Equal(t, *options.WorkspaceAccess.StateVersions, item.WorkspaceAccess.WorkspaceStateVersionsPermission) + assert.Equal(t, *options.WorkspaceAccess.Variables, item.WorkspaceAccess.WorkspaceVariablesPermission) + assert.Equal(t, item.WorkspaceAccess.WorkspaceCreatePermission, true) + assert.Equal(t, item.WorkspaceAccess.WorkspaceLockingPermission, true) + assert.Equal(t, item.WorkspaceAccess.WorkspaceMovePermission, true) + assert.Equal(t, item.WorkspaceAccess.WorkspaceDeletePermission, false) + assert.Equal(t, item.WorkspaceAccess.WorkspaceRunTasksPermission, false) + } + }) + t.Run("with valid options for all custom TeamProject permissions", func(t *testing.T) { options := TeamProjectAccessAddOptions{ Access: *ProjectAccess(TeamProjectAccessCustom), @@ -221,6 +273,45 @@ func TestTeamProjectAccessesAdd(t *testing.T) { } }) + t.Run("with valid options for custom variable sets permissions", func(t *testing.T) { + skipUnlessBeta(t) + options := TeamProjectAccessAddOptions{ + Access: *ProjectAccess(TeamProjectAccessCustom), + Team: tmTest, + Project: pTest, + ProjectAccess: &TeamProjectAccessProjectPermissionsOptions{ + VariableSets: ProjectVariableSetsPermission(ProjectVariableSetsPermissionWrite), + }, + WorkspaceAccess: &TeamProjectAccessWorkspacePermissionsOptions{ + Runs: WorkspaceRunsPermission(WorkspaceRunsPermissionApply), + }, + } + + tpa, err := client.TeamProjectAccess.Add(ctx, options) + t.Cleanup(func() { + err := client.TeamProjectAccess.Remove(ctx, tpa.ID) + if err != nil { + t.Logf("error removing team access (%s): %s", tpa.ID, err) + } + }) + + require.NoError(t, err) + + // Get a refreshed view from the API. + refreshed, err := client.TeamProjectAccess.Read(ctx, tpa.ID) + require.NoError(t, err) + + for _, item := range []*TeamProjectAccess{ + tpa, + refreshed, + } { + assert.NotEmpty(t, item.ID) + assert.Equal(t, options.Access, item.Access) + assert.Equal(t, *options.ProjectAccess.VariableSets, item.ProjectAccess.ProjectVariableSetsPermission) + assert.Equal(t, *options.WorkspaceAccess.Runs, item.WorkspaceAccess.WorkspaceRunsPermission) + } + }) + t.Run("with valid options for some custom TeamProject permissions", func(t *testing.T) { options := TeamProjectAccessAddOptions{ Access: *ProjectAccess(TeamProjectAccessCustom), @@ -389,6 +480,48 @@ func TestTeamProjectAccessesUpdate(t *testing.T) { assert.Equal(t, true, tpa.WorkspaceAccess.WorkspaceRunTasksPermission) }) + t.Run("with valid custom permissions attributes for variable sets permissions", func(t *testing.T) { + skipUnlessBeta(t) + // create tpaCustomTest to verify unupdated attributes stay the same for custom permissions + // because going from admin to read to custom changes the values of all custom permissions + tm2Test, tm2TestCleanup := createTeam(t, client, orgTest) + defer tm2TestCleanup() + + TpaOptions := TeamProjectAccessAddOptions{ + Access: *ProjectAccess(TeamProjectAccessCustom), + Team: tm2Test, + Project: pTest, + } + + tpaCustomTest, err := client.TeamProjectAccess.Add(ctx, TpaOptions) + require.NoError(t, err) + + options := TeamProjectAccessUpdateOptions{ + Access: ProjectAccess(TeamProjectAccessCustom), + ProjectAccess: &TeamProjectAccessProjectPermissionsOptions{ + VariableSets: ProjectVariableSetsPermission(ProjectVariableSetsPermissionRead), + }, + WorkspaceAccess: &TeamProjectAccessWorkspacePermissionsOptions{ + Create: Bool(false), + }, + } + + tpa, err := client.TeamProjectAccess.Update(ctx, tpaCustomTest.ID, options) + require.NoError(t, err) + require.NotNil(t, options.ProjectAccess) + require.NotNil(t, options.WorkspaceAccess) + assert.Equal(t, *options.ProjectAccess.VariableSets, tpa.ProjectAccess.ProjectVariableSetsPermission) + assert.Equal(t, false, tpa.WorkspaceAccess.WorkspaceCreatePermission) + // assert that other attributes remain the same + assert.Equal(t, tpaCustomTest.ProjectAccess.ProjectSettingsPermission, tpa.ProjectAccess.ProjectSettingsPermission) + assert.Equal(t, tpaCustomTest.WorkspaceAccess.WorkspaceLockingPermission, tpa.WorkspaceAccess.WorkspaceLockingPermission) + assert.Equal(t, tpaCustomTest.WorkspaceAccess.WorkspaceMovePermission, tpa.WorkspaceAccess.WorkspaceMovePermission) + assert.Equal(t, tpaCustomTest.WorkspaceAccess.WorkspaceDeletePermission, tpa.WorkspaceAccess.WorkspaceDeletePermission) + assert.Equal(t, tpaCustomTest.WorkspaceAccess.WorkspaceRunsPermission, tpa.WorkspaceAccess.WorkspaceRunsPermission) + assert.Equal(t, tpaCustomTest.WorkspaceAccess.WorkspaceSentinelMocksPermission, tpa.WorkspaceAccess.WorkspaceSentinelMocksPermission) + assert.Equal(t, tpaCustomTest.WorkspaceAccess.WorkspaceStateVersionsPermission, tpa.WorkspaceAccess.WorkspaceStateVersionsPermission) + }) + t.Run("with valid custom permissions attributes for some permissions", func(t *testing.T) { // create tpaCustomTest to verify unupdated attributes stay the same for custom permissions // because going from admin to read to custom changes the values of all custom permissions @@ -429,6 +562,7 @@ func TestTeamProjectAccessesUpdate(t *testing.T) { assert.Equal(t, tpaCustomTest.WorkspaceAccess.WorkspaceSentinelMocksPermission, tpa.WorkspaceAccess.WorkspaceSentinelMocksPermission) assert.Equal(t, tpaCustomTest.WorkspaceAccess.WorkspaceStateVersionsPermission, tpa.WorkspaceAccess.WorkspaceStateVersionsPermission) }) + t.Run("with invalid custom permissions attributes", func(t *testing.T) { options := TeamProjectAccessUpdateOptions{ Access: ProjectAccess(TeamProjectAccessCustom), diff --git a/type_helpers.go b/type_helpers.go index 1ca99d2e5..24252f273 100644 --- a/type_helpers.go +++ b/type_helpers.go @@ -29,6 +29,11 @@ func ProjectTeamsPermission(v ProjectTeamsPermissionType) *ProjectTeamsPermissio return &v } +// ProjectVariableSetsPermission returns a pointer to the given team access project type. +func ProjectVariableSetsPermission(v ProjectVariableSetsPermissionType) *ProjectVariableSetsPermissionType { + return &v +} + // WorkspaceRunsPermission returns a pointer to the given team access project type. func WorkspaceRunsPermission(v WorkspaceRunsPermissionType) *WorkspaceRunsPermissionType { return &v