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

Adding support for Terraform plan target #97

Merged
merged 4 commits into from
Apr 3, 2024
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# UNRELEASED

## Enhancements
* Adds support for Terraform target under `run create` command by @trutled3 [#97](https://github.com/hashicorp/tfc-workflows-tooling/pull/97)

# v1.2.0

## Enhancements
Expand Down
2 changes: 2 additions & 0 deletions docs/ADOPTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ View the GitLab [Base-Template](https://github.com/hashicorp/tfc-workflows-gitla
| Plan | `terraform plan` | commands: `upload`, `run create` |
| Apply | `terraform apply -auto-approve` | commands: `upload`, `run create`, `run apply`|
| Destroy | `terraform plan -destroy -out=destroy.tfplan` , `terraform apply destroy.tfplan`| commands: `run create -is-destroy=true` |
| Target | `terraform plan -target aws_instance.foo` | commands: `run create -target=aws_instance.foo` |

#### Terraform Plan

Expand All @@ -47,6 +48,7 @@ Terraform Cloud CLI can execute a new plan with one command that will upload Ter
With Tfci and Terraform Cloud API driven runs, these actions are broken up into multiple parts:
- Upload terraform configuration as a ConfigurationVersion
- Create a new run using that Configuration Version. If the run was not specified as `plan-only`, then it could be optionally approved or applied.
- Focus Terraform's attention on only a subset of resources with the `target` option.

#### Terraform Apply

Expand Down
2 changes: 2 additions & 0 deletions internal/cloud/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ type CreateRunOptions struct {
IsDestroy bool
SavePlan bool
RunVariables []*tfe.RunVariable
TargetAddrs []string
}

type ApplyRunOptions struct {
Expand Down Expand Up @@ -161,6 +162,7 @@ func (service *runService) CreateRun(ctx context.Context, options CreateRunOptio
createOpts.IsDestroy = tfe.Bool(options.IsDestroy)
createOpts.SavePlan = tfe.Bool(options.SavePlan)
createOpts.Variables = options.RunVariables
createOpts.TargetAddrs = options.TargetAddrs

// create the run
run, err := service.tfe.Runs.Create(ctx, createOpts)
Expand Down
22 changes: 22 additions & 0 deletions internal/cloud/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,28 @@ func TestRunService_CreateRun(t *testing.T) {
},
finalStatus: tfe.RunPlannedAndFinished,
},
{
name: "target-run",
orgName: "test",
workspaceName: "my-workspace",
ctx: context.Background(),
tfeWorkspace: &tfe.Workspace{ID: "ws-***"},
tfeConfigVersion: &tfe.ConfigurationVersion{
ID: "cv-***",
Status: tfe.ConfigurationUploaded,
},
tfeRun: &tfe.Run{
ID: "run-***",
TargetAddrs: []string{"aws_instance.foo", "aws_s3_bucket.bar"},
},
statusChanges: []tfe.RunStatus{
tfe.RunPlanning,
tfe.RunPlanning,
tfe.RunCostEstimated,
tfe.RunPolicyChecked,
},
finalStatus: tfe.RunPlannedAndFinished,
},
{
name: "auto-apply-run",
orgName: "test",
Expand Down
22 changes: 22 additions & 0 deletions internal/command/run_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,30 @@ type CreateRunCommand struct {
Workspace string
ConfigurationVersionID string
Message string
TargetAddrs []string

PlanOnly bool
IsDestroy bool
SavePlan bool
}

// flagStringSlice is a flag.Value implementation which allows collecting
// multiple instances of a single flag into a slice. This is used for flags
// such as -target=aws_instance.foo and -var x=y.
type flagStringSlice []string

var _ flag.Value = (*flagStringSlice)(nil)

func (v *flagStringSlice) String() string {
return strings.Join(*v, ",")
}
func (v *flagStringSlice) Set(raw string) error {
targetSegments := strings.Split(raw, ",")
*v = append(*v, targetSegments...)

return nil
}

func (c *CreateRunCommand) flags() *flag.FlagSet {
f := c.flagSet("run create")
f.StringVar(&c.Workspace, "workspace", "", "The name of the Terraform Cloud Workspace.")
Expand All @@ -33,6 +51,7 @@ func (c *CreateRunCommand) flags() *flag.FlagSet {
f.BoolVar(&c.PlanOnly, "plan-only", false, "Specifies if this is a Terraform Cloud speculative, plan-only run that cannot be applied.")
f.BoolVar(&c.IsDestroy, "is-destroy", false, "Specifies that the plan is a destroy plan. When true, the plan destroys all provisioned resources.")
f.BoolVar(&c.SavePlan, "save-plan", false, "Specifies whether to create a saved plan. Saved-plan runs perform their plan and checks immediately, but won't lock the workspace and become its current run until they are confirmed for apply.")
f.Var((*flagStringSlice)(&c.TargetAddrs), "target", "Limit the planning operation to only the given module, resource, or resource instance and all of its dependencies. You can use this option multiple times to include more than one object. This is for exceptional use only. e.g. -target=aws_s3_bucket.foo")
return f
}

Expand All @@ -57,6 +76,7 @@ func (c *CreateRunCommand) Run(args []string) int {
IsDestroy: c.IsDestroy,
SavePlan: c.SavePlan,
RunVariables: runVars,
TargetAddrs: c.TargetAddrs,
})
if run != nil {
c.readPlanLogs(run)
Expand Down Expand Up @@ -159,6 +179,8 @@ Options:
-plan-only Specifies if this is a Terraform Cloud speculative, plan-only run that cannot be applied.

-save-plan Specifies whether to create a saved plan. Saved-plan runs perform their plan and checks immediately, but won't lock the workspace and become its current run until they are confirmed for apply.
-is-destroy Specifies whether to create a destroy run.
-target Focuses Terraform's attention on only a subset of resources and their dependencies. This option accepts multiple instances by providing additional target option flags.
`
return strings.TrimSpace(helpText)
}
Expand Down
Loading