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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
bin/tfcloud
.plans/
dist/
10 changes: 8 additions & 2 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,23 @@ linters:
- unconvert
settings:
errcheck:
check-blank: true
check-blank: false
misspell:
locale: US
exclusions:
generated: lax
rules:
- linters:
- misspell
path: internal/commands/profile/profile_test.go
- linters:
- bodyclose
- errcheck
- revive
path: _test\.go
- linters:
- revive
path: testing.go
- path: (.+)\.go$
text: ifElseChain
- path: (.+)\.go$
Expand All @@ -39,7 +45,7 @@ formatters:
settings:
goimports:
local-prefixes:
- github.com/hashicorp/hcloud
- github.com/hashicorp/tfcloud
exclusions:
generated: lax
paths:
Expand Down
3 changes: 1 addition & 2 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
version: 2
before:
hooks:
- make go/tidy
- go mod tidy
builds:
- id: default
main: .
env:
- CGO_ENABLED=0
mod_timestamp: "{{ .CommitTimestamp }}"
Expand Down
16 changes: 15 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,23 @@ bin: $(BIN_PATH)

.PHONY: $(BIN_PATH)
$(BIN_PATH):
CGO_ENABLED=0 go build -o $(BIN_PATH) -trimpath -buildvcs=false ./cmd
CGO_ENABLED=0 go build -o $(BIN_PATH) -trimpath -buildvcs=false ./

.PHONY: clean
clean:
rm -rf $(CURDIR)/$(dir $(BIN_PATH))

.PHONY: gen/screenshot
gen/screenshot: go/install ## Create a screenshot of the tfcloud CLI
@go run github.com/homeport/termshot/cmd/termshot@v0.6.1 -c -f assets/tfcloud.png -- tfcloud

.PHONY: go/build
go/build: bin

.PHONY: go/install
go/install:
@go install

.PHONY: go/lint
go/lint:
@golangci-lint run
86 changes: 22 additions & 64 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@

Effectively interact with the HCP Terraform platform.

![tfcloud](assets/tfcloud.png "tfcloud")

#### Quick Start

tfcloud uses a host-centric, layered configuration with a logical precedence. Configuration commands
do not yet exist in the CLI, so start by writing this file to `$HOME/.config/tfcloud/tfcloud.hcl`
(or `%AppData%/tfcloud/tfcloud.hcl` on Windows) substituting your own hostname, token, and organization.
do not yet exist in the CLI, so start by writing this file to `$HOME/.config/tfcloud/profiles/default.hcl`
(or `%AppData%/tfcloud/profiles/default.hcl` on Windows) substituting your own hostname, token, and organization.

```hcl
profile "default" "app.terraform.io" {
token = "your-token"
organization = "user-org"
}
name = "default"
organization = "default-organization"
hostname = "app.staging.terraform.io"
token = "TOKEN"
```

```
Expand Down Expand Up @@ -47,81 +49,37 @@ tfcloud api /organizations/acme/workspaces -paginate -method GET -f "sort=-creat

**Profile-level Configuration**

Linux/MacOS: `~/.config/tfcloud/tfcloud.hcl`
Windows: `%AppData%/tfcloud/tfcloud.hcl`

**Working Directory Configuration**

Working directory config overwrites profile-level config, when available.
The CLI uses a default profile for now, but will eventually support a global --profile named profile.

`.tfcloud.hcl`
Linux/MacOS: `~/.config/tfcloud/profiles/default.hcl`
Windows: `%AppData%/tfcloud/profiles/default.hcl`

**Token created by `terraform login`**

`~/.terraform.d/credentials.tfrc.json` is checked for the configured hostname if the token is not set by configuration file.

**Token in Environment Variables**
**Environment Variable Configuration**

If information is not found in the profile, the following environment variables will be used for configuration:

`TFCLOUD_ORGANIZATION`: The default organization to use, where one might apply.

`TFCLOUD_HOSTNAME`: The Terraform Enterprise or HCP Terraform hostname to use. (Defaults to `app.terraform.io`)

`TFCLOUD_TOKEN`: An API token to use in conjunction with the default profile, only used if token is not set by any other configuration file.
`TFCLOUD_TOKEN`: An API token to use in conjunction with the default profile.

`TFCLOUD_TOKEN_<profile>`: Reserved for future use with multiple profiles.

`TF_TOKEN_<hostname>`: An API token to use with the specified hostname with punycode formatting, e.g. `TF_TOKEN_app_terraform_io`, only used if the token is not specified in any other way.


#### Usage

You can use `tfcloud -help` for detailed usage instructions.
You can use `tfcloud --help` for detailed usage instructions.

**`tfcloud api <path> [flags]`**

Perform an API request.

`-H, -header <key:value>`
Add a HTTP request header in key:value format

`-i, -input <file>`
The file to use as body for the HTTP request (use "-" to read from standard input)

`-X, -method <string>`
The HTTP method for the request (default "GET", unless using -a attributes)

`-t, -type <string>`
When used with a JSON:API request body for POST/PATCH, the resource type (default to the resource implied by the path)

`-paginate`
Make additional HTTP requests to fetch all pages of results but emit in a streamable manner

`-a, -attribute <key=value>`
Add a typed resource attribute to the request body in key=value format

`-f, -field <key=value>`
Add a query string parameter to the request URL in key=value format

`-agent`
Print the raw response body.

`-json`
Print the raw response body, colorized, if a terminal is attached.

`-v, -verbose`
Log HTTP request and response details to stderr
Perform an API request. See `tfcloud api --help` for usage and examples.

**`tfcloud variable import [tfvars-file] [flags]`**

Import variables from a tfvars file or the process environment into the current workspace or a variable set.

`-e <name>`
Import an environment variable by name. Repeat to import multiple values.

`-variable-set-name <name>`
Target a variable set by name instead of the current workspace.

`-organization <string>`
Organization name. Optional when it can be resolved from the default organization in `tfcloud.hcl` or local Terraform configuration.

`-workspace <string>`
Override the target workspace name.

`-overwrite`
Update matching existing variables instead of failing when duplicates are found.
Import variables from a tfvars file or the process environment into the current workspace or a variable set. See `tfcloud variable import --help` for usage and examples.
Binary file added assets/tfcloud.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
63 changes: 0 additions & 63 deletions cmd/tfcloud.go

This file was deleted.

80 changes: 50 additions & 30 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,67 +1,87 @@
module github.com/brandonc/tfcloud
module github.com/hashicorp/tfcloud

go 1.25.5

require (
github.com/Masterminds/semver/v3 v3.2.0
github.com/charmbracelet/lipgloss v1.1.0
github.com/MakeNowJust/heredoc/v2 v2.0.1
github.com/dustin/go-humanize v1.0.1
github.com/go-openapi/runtime v0.29.3
github.com/hashicorp/cli v1.1.7
github.com/hashicorp/go-hclog v1.6.3
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/go-tfe v1.78.1-0.20260401171829-7a49f0cf5cb4
github.com/hashicorp/go-version v1.9.0
github.com/hashicorp/hcl/v2 v2.24.0
github.com/mattn/go-isatty v0.0.20
github.com/lithammer/dedent v1.1.0
github.com/microsoft/kiota-abstractions-go v1.9.4
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/mapstructure v1.5.0
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6
github.com/muesli/reflow v0.3.0
github.com/muesli/termenv v0.16.0
github.com/posener/complete v1.2.3
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.11.1
github.com/zclconf/go-cty v1.16.3
golang.org/x/net v0.43.0
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f
golang.org/x/net v0.50.0
golang.org/x/term v0.40.0
)

require (
dario.cat/mergo v1.0.1 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
github.com/agext/levenshtein v1.2.1 // indirect
github.com/Masterminds/semver/v3 v3.3.1 // indirect
github.com/Masterminds/sprig/v3 v3.3.0 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/armon/go-radix v1.0.0 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/bgentry/speakeasy v0.1.0 // indirect
github.com/bgentry/speakeasy v0.2.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
github.com/charmbracelet/x/ansi v0.8.0 // indirect
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
github.com/charmbracelet/x/term v0.2.1 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/errors v0.22.7 // indirect
github.com/go-openapi/strfmt v0.26.0 // indirect
github.com/go-openapi/swag/conv v0.25.5 // indirect
github.com/go-openapi/swag/fileutils v0.25.5 // indirect
github.com/go-openapi/swag/jsonutils v0.25.5 // indirect
github.com/go-openapi/swag/stringutils v0.25.5 // indirect
github.com/go-openapi/swag/typeutils v0.25.5 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-multierror v1.0.0 // indirect
github.com/huandu/xstrings v1.3.3 // indirect
github.com/imdario/mergo v0.3.11 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/huandu/xstrings v1.5.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/microsoft/kiota-http-go v1.5.5 // indirect
github.com/microsoft/kiota-serialization-form-go v1.1.3 // indirect
github.com/microsoft/kiota-serialization-json-go v1.1.2 // indirect
github.com/microsoft/kiota-serialization-multipart-go v1.1.2 // indirect
github.com/microsoft/kiota-serialization-text-go v1.1.3 // indirect
github.com/mitchellh/copystructure v1.0.0 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/reflectwalk v1.0.0 // indirect
github.com/muesli/termenv v0.16.0 // indirect
github.com/posener/complete v1.2.3 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/oklog/ulid/v2 v2.1.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/spf13/cast v1.7.0 // indirect
github.com/std-uritemplate/std-uritemplate/go/v2 v2.0.8 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/otel v1.43.0 // indirect
go.opentelemetry.io/otel/metric v1.43.0 // indirect
go.opentelemetry.io/otel/trace v1.43.0 // indirect
golang.org/x/crypto v0.41.0 // indirect
golang.org/x/mod v0.26.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/sys v0.35.0 // indirect
golang.org/x/text v0.28.0 // indirect
golang.org/x/tools v0.35.0 // indirect
golang.org/x/crypto v0.48.0 // indirect
golang.org/x/mod v0.32.0 // indirect
golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.41.0 // indirect
golang.org/x/text v0.34.0 // indirect
golang.org/x/tools v0.41.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading
Loading