Skip to content

Commit

Permalink
TFx 0.1.0 release prep (#26)
Browse files Browse the repository at this point in the history
* tfx workspace cv list, "workspaceName" to "workspace-name"
* tfx release list (tfe and replicated), added `--all` flag
* tfx registry list (module and provider), added `--max-items` and `--all` flags
* fixed bug with registry module version create when the module did not exist
  • Loading branch information
straubt1 committed Aug 21, 2022
1 parent 7af8393 commit 905e66e
Show file tree
Hide file tree
Showing 19 changed files with 134 additions and 70 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: main
name: Build `tfx` - Cross Compile

on:
push:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: release
name: Release `tfx`

on:
release:
Expand Down
19 changes: 14 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,17 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.0.5] - 2022.08.20
## [Unreleased]

**Added**

**Changed**

**Removed**

## [0.1.0] - 2022.08.21

First official release!

**Added**

Expand All @@ -14,7 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
**Changed**

* Moved and updated docs to the `site/` folder and published to a custom domain [tfx.rocks](tfx.rocks).
* Created a styleguide and updated Commands, more information can be found at [https://tfx.rocks/about/style_guide/]()
* Created a style guide and updated Commands, more information can be found at [https://tfx.rocks/about/style_guide/]()
* Some of these changes are **BREAKING** changes
* Mainly moving away from Command Flags that used camel case (example: "workspaceName" to "workspace-name")
* Updated all of the `tfx registry module` commands to support JSON (`--json`) output.
Expand Down Expand Up @@ -191,6 +201,5 @@ New Commands:

**Removed**

[Unreleased]: https://github.com/straubt1/tfx/compare/v1.0.0...HEAD
[0.0.1]: https://github.com/ostraubt1/tfx/compare/v0.0.0...v0.0.1
[0.0.0]: https://github.com/straubt1/tfx/releases/tag/v0.0.1
[Unreleased]: https://github.com/straubt1/tfx/compare/v0.1.0...HEAD
[0.1.0]: https://github.com/straubt1/tfx/releases/tag/v0.1.0
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!-- <img src="https://cdn.rawgit.com/hashicorp/terraform-website/master/content/source/assets/images/logo-hashicorp.svg" width="600px">
-->
# Terraform Cloud/Enterprise CLI
# Terraform Cloud/Terraform Enterprise CLI

[![main](https://github.com/straubt1/tfx/actions/workflows/main.yml/badge.svg)](https://github.com/straubt1/tfx/actions/workflows/main.yml)
![Go Version](https://img.shields.io/badge/go%20version-%3E=1.18-61CFDD.svg?style=flat-square)
Expand All @@ -15,3 +15,15 @@ The initial focus of _tfx_ was to execute the API-Driven workflow for a Workspac

Looking for more information?
Check out our docs site [tfx.rocks](https://tfx.rocks)

## General Roadmap

Future implementation items:

- [ ] Create testing setup
- [ ] Refactor `plan` and `apply` workflow
- [ ] Support Variable Sets
- [ ] Support Sentinel Publishing
- [ ] Support Cloud Agents

Priority may changes, please submit an issue to voice changes you would like to see.
6 changes: 3 additions & 3 deletions cmd/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ var (

func init() {
// All `tfx apply` commands
applyCmd.PersistentFlags().StringP("runId", "i", "", "Run Id to apply")
applyCmd.PersistentFlags().StringP("run-id", "i", "", "Run Id to apply")

applyCmd.MarkPersistentFlagRequired("runId")
applyCmd.MarkPersistentFlagRequired("run-id")

rootCmd.AddCommand(applyCmd)
}
Expand All @@ -57,7 +57,7 @@ func runApply() error {
hostname := *viperString("tfeHostname")
orgName := *viperString("tfeOrganization")
wsName := *viperString("workspaceName")
runID := *viperString("runId")
runID := *viperString("run-id")

client, ctx := getClientContext()

Expand Down
1 change: 1 addition & 0 deletions cmd/helper_rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ type GPGList struct {
}

func ListGPGKeys(c TfxClientContext) (*GPGList, error) {
// TODO: No pagination, waiting on go-tfe to provide a List function since it is unlikely an org would have more than 100 keys
// create url "https://${HOST}/api/registry/private/v2/gpg-keys?filter%5Bnamespace%5D=${provider_namespace}"
url := fmt.Sprintf(
"https://%s/api/registry/private/v2/gpg-keys?filter[namespace]=%s",
Expand Down
18 changes: 9 additions & 9 deletions cmd/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,18 @@ var (

func init() {
// All `tfx plan` commands
planCmd.Flags().StringP("workspaceName", "w", "", "Workspace name")
planCmd.Flags().StringP("workspace-name", "w", "", "Workspace name")
planCmd.Flags().StringP("directory", "d", "./", "Directory of Terraform (optional, defaults to current directory)")
planCmd.Flags().StringP("configurationId", "i", "", "Configuration Version Id (optional, i.e. cv-*)")
planCmd.Flags().StringP("configuration-id", "i", "", "Configuration Version Id (optional, i.e. cv-*)")
planCmd.Flags().StringP("message", "m", "", "Run Message (optional)")
planCmd.Flags().Bool("speculative", false, "Perform a Speculative Plan (optional)")
planCmd.Flags().Bool("destroy", false, "Perform a Destroy Plan (optional)")
planCmd.Flags().StringSlice("env", []string{}, "Environment variables to write to the Workspace. Can be suplied multiple times. (optional, i.e. '--env='AWS_REGION=us-east1')")
planCmd.MarkFlagRequired("workspaceName")
planCmd.Flags().StringSlice("env", []string{}, "Environment variables to write to the Workspace. Can be supplied multiple times. (optional, i.e. '--env='AWS_REGION=us-east1')")
planCmd.MarkFlagRequired("workspace-name")

planExportCmd.Flags().StringP("planId", "i", "", "Plan Id (i.e. plan-*)")
planExportCmd.Flags().StringP("plan-id", "i", "", "Plan Id (i.e. plan-*)")
planExportCmd.Flags().StringP("directory", "d", "", "Directory to download export to (optional, defaults to a temp directory)")
planExportCmd.MarkFlagRequired("planId")
planExportCmd.MarkFlagRequired("plan-id")
planExportCmd.MarkFlagRequired("directory")

rootCmd.AddCommand(planCmd)
Expand All @@ -79,9 +79,9 @@ func runPlan() error {
// Validate flags
hostname := *viperString("tfeHostname")
orgName := *viperString("tfeOrganization")
wsName := *viperString("workspaceName")
wsName := *viperString("workspace-name")
dir := *viperString("directory")
configID := *viperString("configurationId")
configID := *viperString("configuration-id")
message := *viperString("message")
isSpeculative := *viperBool("speculative")
isDestroy := *viperBool("destroy")
Expand Down Expand Up @@ -156,7 +156,7 @@ func runPlan() error {
}

func runPlanExport() error {
planID := *viperString("planId")
planID := *viperString("plan-id")
directory := *viperString("directory")
client, ctx := getClientContext()

Expand Down
32 changes: 24 additions & 8 deletions cmd/registry_module.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
package cmd

import (
"math"

tfe "github.com/hashicorp/go-tfe"
"github.com/pkg/errors"
"github.com/spf13/cobra"
Expand All @@ -40,8 +42,14 @@ var (
Short: "List modules",
Long: "List modules in the Private Module Registry of a TFx Organization.",
RunE: func(cmd *cobra.Command, args []string) error {
m := *viperInt("max-items")
if *viperBool("all") {
m = math.MaxInt
}

return registryModuleList(
getTfxClientContext())
getTfxClientContext(),
m)
},
}

Expand Down Expand Up @@ -87,6 +95,8 @@ var (

func init() {
// `tfx registry module list` arguments
registryModuleListCmd.Flags().IntP("max-items", "m", 10, "Max number of results (optional)")
registryModuleListCmd.Flags().BoolP("all", "a", false, "Retrieve all results regardless of maxItems flag (optional)")

// `tfx registry module create` arguments
registryModuleCreateCmd.Flags().StringP("name", "n", "", "Name of the Module (no spaces)")
Expand All @@ -113,13 +123,15 @@ func init() {
registryModuleCmd.AddCommand(registryModuleDeleteCmd)
}

func registryModuleListAll(c TfxClientContext, orgName string) ([]*tfe.RegistryModule, error) {
func registryModuleListAll(c TfxClientContext, orgName string, maxItems int) ([]*tfe.RegistryModule, error) {
pageSize := 100
if maxItems < 100 {
pageSize = maxItems // Only get what we need in one page
}

allItems := []*tfe.RegistryModule{}
opts := tfe.RegistryModuleListOptions{
ListOptions: tfe.ListOptions{
PageNumber: 1,
PageSize: 100,
},
ListOptions: tfe.ListOptions{PageNumber: 1, PageSize: pageSize},
}

for {
Expand All @@ -129,6 +141,10 @@ func registryModuleListAll(c TfxClientContext, orgName string) ([]*tfe.RegistryM
}

allItems = append(allItems, items.Items...)
if len(allItems) >= maxItems {
break // Hit the max, break. For maxItems > 100 it is possible to return more than max in this approach
}

if items.CurrentPage >= items.TotalPages {
break
}
Expand All @@ -138,9 +154,9 @@ func registryModuleListAll(c TfxClientContext, orgName string) ([]*tfe.RegistryM
return allItems, nil
}

func registryModuleList(c TfxClientContext) error {
func registryModuleList(c TfxClientContext, maxItems int) error {
o.AddMessageUserProvided("List Modules for Organization:", c.OrganizationName)
items, err := registryModuleListAll(c, c.OrganizationName)
items, err := registryModuleListAll(c, c.OrganizationName, maxItems)
if err != nil {
return errors.Wrap(err, "failed to list modules")
}
Expand Down
17 changes: 9 additions & 8 deletions cmd/registry_module_version.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ var (
)

func init() {
// `tfx registry module version list` arguments
registryModuleVersionListCmd.Flags().StringP("name", "n", "", "Name of the Module (no spaces)")
registryModuleVersionListCmd.Flags().StringP("provider", "p", "", "Name of the provider (no spaces) (i.e. aws, azure, google)")
registryModuleVersionListCmd.MarkFlagRequired("name")
registryModuleVersionListCmd.MarkFlagRequired("provider")

// `tfx registry module version create` arguments
registryModuleVersionCreateCmd.Flags().StringP("name", "n", "", "Name of the Module (no spaces)")
registryModuleVersionCreateCmd.Flags().StringP("provider", "p", "", "Name of the provider (no spaces) (i.e. aws, azure, google)")
Expand All @@ -125,12 +131,6 @@ func init() {
registryModuleVersionCreateCmd.MarkFlagRequired("provider")
registryModuleVersionCreateCmd.MarkFlagRequired("version")

// `tfx registry module version list` arguments
registryModuleVersionListCmd.Flags().StringP("name", "n", "", "Name of the Module (no spaces)")
registryModuleVersionListCmd.Flags().StringP("provider", "p", "", "Name of the provider (no spaces) (i.e. aws, azure, google)")
registryModuleVersionListCmd.MarkFlagRequired("name")
registryModuleVersionListCmd.MarkFlagRequired("provider")

// `tfx registry module version delete` arguments
registryModuleVersionDeleteCmd.Flags().StringP("name", "n", "", "Name of the Module (no spaces)")
registryModuleVersionDeleteCmd.Flags().StringP("provider", "p", "", "Name of the provider (no spaces) (i.e. aws, azure, google)")
Expand Down Expand Up @@ -189,9 +189,10 @@ func registryModuleVersionCreate(c TfxClientContext, moduleName string, provider
Version: &moduleVersion,
})
if err != nil {
errors.Wrap(err, "failed to create module version")
return errors.Wrap(err, "failed to create module version")
}
o.AddMessageUserProvided("Module Created, Uploading...", "")

o.AddMessageUserProvided("Module Version Created, Uploading...", "")
err = c.Client.RegistryModules.Upload(c.Context, *module, directory)
if err != nil {
errors.Wrap(err, "failed to upload module version")
Expand Down
32 changes: 24 additions & 8 deletions cmd/registry_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
package cmd

import (
"math"

tfe "github.com/hashicorp/go-tfe"
"github.com/pkg/errors"
"github.com/spf13/cobra"
Expand All @@ -39,8 +41,14 @@ var (
Short: "List Providers in a Private Registry",
Long: "List Providers in a Private Registry of a TFx Organization.",
RunE: func(cmd *cobra.Command, args []string) error {
m := *viperInt("max-items")
if *viperBool("all") {
m = math.MaxInt
}

return registryProviderList(
getTfxClientContext())
getTfxClientContext(),
m)
},
}

Expand Down Expand Up @@ -83,6 +91,8 @@ var (

func init() {
// `tfx registry provider list` arguments
registryProviderListCmd.Flags().IntP("max-items", "m", 10, "Max number of results (optional)")
registryProviderListCmd.Flags().BoolP("all", "a", false, "Retrieve all results regardless of maxItems flag (optional)")

// `tfx registry provider create` arguments
registryProviderCreateCmd.Flags().StringP("name", "n", "", "Name of the Provider")
Expand All @@ -103,14 +113,16 @@ func init() {
registryProviderCmd.AddCommand(registryProviderDeleteCmd)
}

func registryProviderListAll(c TfxClientContext) ([]*tfe.RegistryProvider, error) {
func registryProviderListAll(c TfxClientContext, maxItems int) ([]*tfe.RegistryProvider, error) {
pageSize := 100
if maxItems < 100 {
pageSize = maxItems // Only get what we need in one page
}

allItems := []*tfe.RegistryProvider{}
opts := tfe.RegistryProviderListOptions{
ListOptions: tfe.ListOptions{PageNumber: 1, PageSize: pageSize},
// RegistryName: tfe.PrivateRegistry, // Can restrict to just private
ListOptions: tfe.ListOptions{
PageNumber: 1,
PageSize: 100,
},
// Include: &[]tfe.RegistryProviderIncludeOps{"provider-versions"}, does not work, cant get provider versions from this call?
}
for {
Expand All @@ -120,6 +132,10 @@ func registryProviderListAll(c TfxClientContext) ([]*tfe.RegistryProvider, error
}

allItems = append(allItems, items.Items...)
if len(allItems) >= maxItems {
break // Hit the max, break. For maxItems > 100 it is possible to return more than max in this approach
}

if items.CurrentPage >= items.TotalPages {
break
}
Expand All @@ -129,9 +145,9 @@ func registryProviderListAll(c TfxClientContext) ([]*tfe.RegistryProvider, error
return allItems, nil
}

func registryProviderList(c TfxClientContext) error {
func registryProviderList(c TfxClientContext, maxItems int) error {
o.AddMessageUserProvided("List Providers in Registry for Organization:", c.OrganizationName)
items, err := registryProviderListAll(c)
items, err := registryProviderListAll(c, maxItems)
if err != nil {
return errors.Wrap(err, "failed to list providers")
}
Expand Down
11 changes: 9 additions & 2 deletions cmd/release_replicated.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package cmd

import (
"fmt"
"math"
"strings"

"github.com/mmcdole/gofeed"
Expand All @@ -42,8 +43,13 @@ var (
Short: "List Replicated binaries",
Long: "List available Replicated releases.",
RunE: func(cmd *cobra.Command, args []string) error {
m := *viperInt("max-items")
if *viperBool("all") {
m = math.MaxInt
}

return releaseReplicatedList(
*viperInt("max-items"))
m)
},
}

Expand All @@ -70,7 +76,8 @@ var (

func init() {
// `tfx release replicated list`
releaseReplicatedListCmd.Flags().IntP("max-items", "r", 10, "The number of results to print")
releaseReplicatedListCmd.Flags().IntP("max-items", "m", 10, "The number of results to print")
releaseReplicatedListCmd.Flags().BoolP("all", "a", false, "Retrieve all results regardless of maxItems flag (optional)")

// `tfx release replicated download`
releaseReplicatedDownloadCmd.Flags().StringP("directory", "d", "./", "Directory to save binary")
Expand Down
Loading

0 comments on commit 905e66e

Please sign in to comment.