Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OPA support for task stages #584

Merged
merged 6 commits into from Nov 14, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,7 @@
* Add OPA support to the Policy Set APIs by @mrinalirao [#575](https://github.com/hashicorp/go-tfe/pull/575)
* Add OPA support to the Policy APIs by @mrinalirao [#579](https://github.com/hashicorp/go-tfe/pull/579)
* Add Policy Evaluation and Policy Set Outcome APIs by @mrinalirao [#583](https://github.com/hashicorp/go-tfe/pull/583)
* Add OPA support to Task Stage APIs by @mrinalirao [#584](https://github.com/hashicorp/go-tfe/pull/584)

# v1.12.0

Expand Down
30 changes: 30 additions & 0 deletions helper_test.go
Expand Up @@ -556,6 +556,36 @@ func createPolicySet(t *testing.T, client *Client, org *Organization, policies [
}
}

func createPolicySetWithOptions(t *testing.T, client *Client, org *Organization, policies []*Policy, workspaces []*Workspace, opts PolicySetCreateOptions) (*PolicySet, func()) {
var orgCleanup func()

if org == nil {
org, orgCleanup = createOrganization(t, client)
}

ctx := context.Background()
ps, err := client.PolicySets.Create(ctx, org.Name, PolicySetCreateOptions{
Name: String(randomString(t)),
Policies: policies,
Workspaces: workspaces,
Kind: opts.Kind,
Overridable: opts.Overridable,
})
if err != nil {
t.Fatal(err)
}
return ps, func() {
if err := client.PolicySets.Delete(ctx, ps.ID); err != nil {
t.Errorf("Error destroying policy set! WARNING: Dangling resources\n"+
"may exist! The full error is shown below.\n\n"+
"PolicySet: %s\nError: %s", ps.ID, err)
}
if orgCleanup != nil {
orgCleanup()
}
}
}

func createPolicySetVersion(t *testing.T, client *Client, ps *PolicySet) (*PolicySetVersion, func()) {
var psCleanup func()

Expand Down
15 changes: 15 additions & 0 deletions mocks/task_stages_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 2 additions & 4 deletions policy_integration_beta_test.go
Expand Up @@ -235,10 +235,9 @@ func TestPoliciesList_Beta(t *testing.T) {
defer pTestCleanup2()
opaOptions := PolicyCreateOptions{
Kind: OPA,
Query: String("terraform.policy1.deny"),
Query: String("data.example.rule"),
Enforce: []*EnforcementOptions{
{
Path: String(".rego"),
Mode: EnforcementMode(EnforcementMandatory),
},
},
Expand Down Expand Up @@ -322,10 +321,9 @@ func TestPoliciesUpdate_Beta(t *testing.T) {
options := PolicyCreateOptions{
Description: String("A sample policy"),
Kind: OPA,
Query: String("terraform.main"),
Query: String("data.example.rule"),
Enforce: []*EnforcementOptions{
{
Path: String(".rego"),
Mode: EnforcementMode(EnforcementMandatory),
},
},
Expand Down
51 changes: 26 additions & 25 deletions run.go
Expand Up @@ -53,31 +53,32 @@ type RunStatus string

// List all available run statuses.
const (
RunApplied RunStatus = "applied"
RunApplying RunStatus = "applying"
RunApplyQueued RunStatus = "apply_queued"
RunCanceled RunStatus = "canceled"
RunConfirmed RunStatus = "confirmed"
RunCostEstimated RunStatus = "cost_estimated"
RunCostEstimating RunStatus = "cost_estimating"
RunDiscarded RunStatus = "discarded"
RunErrored RunStatus = "errored"
RunFetching RunStatus = "fetching"
RunFetchingCompleted RunStatus = "fetching_completed"
RunPending RunStatus = "pending"
RunPlanned RunStatus = "planned"
RunPlannedAndFinished RunStatus = "planned_and_finished"
RunPlanning RunStatus = "planning"
RunPlanQueued RunStatus = "plan_queued"
RunPolicyChecked RunStatus = "policy_checked"
RunPolicyChecking RunStatus = "policy_checking"
RunPolicyOverride RunStatus = "policy_override"
RunPolicySoftFailed RunStatus = "policy_soft_failed"
RunPostPlanCompleted RunStatus = "post_plan_completed"
RunPostPlanRunning RunStatus = "post_plan_running"
RunPrePlanCompleted RunStatus = "pre_plan_completed"
RunPrePlanRunning RunStatus = "pre_plan_running"
RunQueuing RunStatus = "queuing"
RunApplied RunStatus = "applied"
RunApplying RunStatus = "applying"
RunApplyQueued RunStatus = "apply_queued"
RunCanceled RunStatus = "canceled"
RunConfirmed RunStatus = "confirmed"
RunCostEstimated RunStatus = "cost_estimated"
RunCostEstimating RunStatus = "cost_estimating"
RunDiscarded RunStatus = "discarded"
RunErrored RunStatus = "errored"
RunFetching RunStatus = "fetching"
RunFetchingCompleted RunStatus = "fetching_completed"
RunPending RunStatus = "pending"
RunPlanned RunStatus = "planned"
RunPlannedAndFinished RunStatus = "planned_and_finished"
RunPlanning RunStatus = "planning"
RunPlanQueued RunStatus = "plan_queued"
RunPolicyChecked RunStatus = "policy_checked"
RunPolicyChecking RunStatus = "policy_checking"
RunPolicyOverride RunStatus = "policy_override"
RunPolicySoftFailed RunStatus = "policy_soft_failed"
RunPostPlanCompleted RunStatus = "post_plan_completed"
RunPostPlanRunning RunStatus = "post_plan_running"
RunPrePlanCompleted RunStatus = "pre_plan_completed"
RunPrePlanRunning RunStatus = "pre_plan_running"
RunQueuing RunStatus = "queuing"
RunPostPlanAwaitingDecision RunStatus = "post_plan_awaiting_decision"
mrinalirao marked this conversation as resolved.
Show resolved Hide resolved
)

// RunSource represents a source type of a run.
Expand Down
1 change: 1 addition & 0 deletions task_result.go
Expand Up @@ -29,6 +29,7 @@ const (
TaskPending TaskResultStatus = "pending"
TaskRunning TaskResultStatus = "running"
TaskUnreachable TaskResultStatus = "unreachable"
TaskErrored TaskResultStatus = "errored"
)

// TaskEnforcementLevel is an enum that describes the enforcement levels for a run task
Expand Down
65 changes: 64 additions & 1 deletion task_stages.go
Expand Up @@ -15,8 +15,12 @@ type TaskStages interface {
// Read a task stage by ID
Read(ctx context.Context, taskStageID string, options *TaskStageReadOptions) (*TaskStage, error)

// List all task stages for a given rrun
// List all task stages for a given run
List(ctx context.Context, runID string, options *TaskStageListOptions) (*TaskStageList, error)

// **Note: This function is still in BETA and subject to change.**
mrinalirao marked this conversation as resolved.
Show resolved Hide resolved
// Override a task stage for a given run
Override(ctx context.Context, taskStageID string, options TaskStageOverrideOptions) (*TaskStage, error)
}

// taskStages implements TaskStages
Expand All @@ -33,19 +37,51 @@ const (
PreApply Stage = "pre_apply"
)

// TaskStageStatus is an enum that represents all possible statuses for a task stage
type TaskStageStatus string

const (
TaskStagePending TaskStageStatus = "pending"
TaskStageRunning TaskStageStatus = "running"
TaskStagePassed TaskStageStatus = "passed"
TaskStageFailed TaskStageStatus = "failed"
TaskStageAwaitingOverride TaskStageStatus = "awaiting_override"
)

// Permissions represents the permission types for overridding a task stage
type Permissions struct {
CanOverridePolicy *bool `jsonapi:"attr,can-override-policy"`
CanOverrideTasks *bool `jsonapi:"attr,can-override-tasks"`
CanOverride *bool `jsonapi:"attr,can-override"`
}

// Actions represents a task stage actions
type Actions struct {
IsOverridable *bool `jsonapi:"attr, overridable"`
mrinalirao marked this conversation as resolved.
Show resolved Hide resolved
}

// TaskStage represents a TFC/E run's stage where run tasks can occur
type TaskStage struct {
ID string `jsonapi:"primary,task-stages"`
Stage Stage `jsonapi:"attr,stage"`
Status TaskStageStatus `jsonapi:"attr,status"`
StatusTimestamps TaskStageStatusTimestamps `jsonapi:"attr,status-timestamps"`
CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"`
UpdatedAt time.Time `jsonapi:"attr,updated-at,iso8601"`
Permissions *Permissions `jsonapi:"attr,permissions"`
Actions *Actions `jsonapi:"attr,actions"`

Run *Run `jsonapi:"relation,run"`
TaskResults []*TaskResult `jsonapi:"relation,task-results"`
PolicyEvaluations []*PolicyEvaluation `jsonapi:"relation,policy-evaluations"`
}

// TaskStageOverrideOptions represents the options for overriding a TaskStage.
type TaskStageOverrideOptions struct {
// An optional explanation for why the stage was overridden
Comment *string `json:"comment,omitempty"`
}

// TaskStageList represents a list of task stages
type TaskStageList struct {
*Pagination
Expand All @@ -66,6 +102,9 @@ type TaskStageIncludeOpt string

const TaskStageTaskResults TaskStageIncludeOpt = "task_results"

// **Note: This field is still in BETA and subject to change.**
const PolicyEvaluationsTaskResults TaskStageIncludeOpt = "policy_evaluations"

// TaskStageReadOptions represents the set of options when reading a task stage
type TaskStageReadOptions struct {
// Optional: A list of relations to include.
Expand Down Expand Up @@ -123,6 +162,28 @@ func (s *taskStages) List(ctx context.Context, runID string, options *TaskStageL
return tlist, nil
}

// **Note: This function is still in BETA and subject to change.**
// Override a task stages for a run
func (s *taskStages) Override(ctx context.Context, taskStageID string, options TaskStageOverrideOptions) (*TaskStage, error) {
if !validStringID(&taskStageID) {
return nil, ErrInvalidTaskStageID
}

u := fmt.Sprintf("task-stages/%s/actions/override", taskStageID)
req, err := s.client.NewRequest("POST", u, &options)
if err != nil {
return nil, err
}

t := &TaskStage{}
err = req.Do(ctx, t)
if err != nil {
return nil, err
}

return t, nil
}

func (o *TaskStageReadOptions) valid() error {
if o == nil {
return nil // nothing to validate
Expand All @@ -140,6 +201,8 @@ func validateTaskStageIncludeParams(params []TaskStageIncludeOpt) error {
switch p {
case TaskStageTaskResults:
// do nothing
case PolicyEvaluationsTaskResults:
// do nothing
default:
return ErrInvalidIncludeValue
}
Expand Down