Skip to content

Commit

Permalink
feat: generate command rework (#928)
Browse files Browse the repository at this point in the history
* feat: iac generate command rework

The subcommand `cloud-account iac-generate` is now top level `generate` command
  • Loading branch information
jon-stewart authored Oct 5, 2022
1 parent e562429 commit 56cbdcd
Show file tree
Hide file tree
Showing 15 changed files with 263 additions and 197 deletions.
98 changes: 23 additions & 75 deletions cli/cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,100 +5,48 @@ import (
"os"
"path/filepath"
"regexp"
"time"

"github.com/AlecAivazis/survey/v2"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)

type AwsGenerateCommandExtraState struct {
Output string
UseExistingCloudtrail bool
UseExistingSNSTopic bool
AwsSubAccounts []string
TerraformApply bool
}

func (a *AwsGenerateCommandExtraState) isEmpty() bool {
return a.Output == "" && !a.UseExistingCloudtrail && len(a.AwsSubAccounts) == 0 && !a.TerraformApply
}

// Flush current state of the struct to disk, provided it's not empty
func (a *AwsGenerateCommandExtraState) writeCache() {
if !a.isEmpty() {
cli.WriteAssetToCache(CachedAssetAwsExtraState, time.Now().Add(time.Hour*1), a)
}
}

type GcpGenerateCommandExtraState struct {
AskAdvanced bool
Output string
ConfigureNewBucketSettings bool
UseExistingServiceAccount bool
UseExistingBucket bool
UseExistingSink bool
TerraformApply bool
}

func (gcp *GcpGenerateCommandExtraState) isEmpty() bool {
return gcp.Output == "" &&
!gcp.AskAdvanced &&
!gcp.UseExistingServiceAccount &&
!gcp.UseExistingBucket &&
!gcp.UseExistingSink &&
!gcp.TerraformApply
}

// Flush current state of the struct to disk, provided it's not empty
func (gcp *GcpGenerateCommandExtraState) writeCache() {
if !gcp.isEmpty() {
cli.WriteAssetToCache(CachedAssetGcpExtraState, time.Now().Add(time.Hour*1), gcp)
}
}

type AzureGenerateCommandExtraState struct {
Output string
TerraformApply bool
}

func (a *AzureGenerateCommandExtraState) isEmpty() bool {
return a.Output == "" && !a.TerraformApply
}

// Flush current state of the struct to disk, provided it's not empty
func (a *AzureGenerateCommandExtraState) writeCache() {
if !a.isEmpty() {
cli.WriteAssetToCache(CachedAzureAssetExtraState, time.Now().Add(time.Hour*1), a)
}
}

var (
QuestionRunTfPlan = "Run Terraform plan now?"
QuestionUsePreviousCache = "Previous IaC generation detected, load cached values?"

// iac-generate command is used to create IaC code for various environments
iacGenerateTfCommand = &cobra.Command{
Use: "iac-generate",
Aliases: []string{"iac"},
Short: "Create IaC code",
Long: "Create IaC content for various different cloud environments and configurations",
Deprecated: "This command is deprecated. Use 'generate'.",
Hidden: true,
}

generateTfCommand = &cobra.Command{
Use: "iac-generate",
Aliases: []string{"iac"},
Short: "Create IaC code",
Long: "Create IaC content for various different cloud environments and configurations",
Use: "generate",
Aliases: []string{"gen"},
Short: "Generate code to onboard your account",
Long: `Generate code to onboard your account and deploy Lacework into various cloud environments.
This command creates Terraform HCL, Infrastructure as Code, with the option of running
Terraform and deploying Lacework into AWS, Azure, or GCP.
`,
}
)

func init() {
// add the iac-generate command
cloudAccountCommand.AddCommand(generateTfCommand)
rootCmd.AddCommand(generateTfCommand)

// Add cloud specific command flags
//Deprecated
cloudAccountCommand.AddCommand(iacGenerateTfCommand)
initGenerateAwsTfCommandFlags()
initGenerateGcpTfCommandFlags()
initGenerateAzureTfCommandFlags()

// add sub-commands to the iac-generate command
generateTfCommand.AddCommand(generateAwsTfCommand)
generateTfCommand.AddCommand(generateGcpTfCommand)
generateTfCommand.AddCommand(generateAzureTfCommand)
iacGenerateTfCommand.AddCommand(generateAwsTfCommand)
iacGenerateTfCommand.AddCommand(generateGcpTfCommand)
iacGenerateTfCommand.AddCommand(generateAzureTfCommand)
}

type SurveyQuestionWithValidationArgs struct {
Expand Down
19 changes: 19 additions & 0 deletions cli/cmd/generate_aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,25 @@ See help output for more details on the parameter value(s) required for Terrafor
}
)

type AwsGenerateCommandExtraState struct {
Output string
UseExistingCloudtrail bool
UseExistingSNSTopic bool
AwsSubAccounts []string
TerraformApply bool
}

func (a *AwsGenerateCommandExtraState) isEmpty() bool {
return a.Output == "" && !a.UseExistingCloudtrail && len(a.AwsSubAccounts) == 0 && !a.TerraformApply
}

// Flush current state of the struct to disk, provided it's not empty
func (a *AwsGenerateCommandExtraState) writeCache() {
if !a.isEmpty() {
cli.WriteAssetToCache(CachedAssetAwsExtraState, time.Now().Add(time.Hour*1), a)
}
}

func initGenerateAwsTfCommandFlags() {
// add flags to sub commands
// TODO Share the help with the interactive generation
Expand Down
16 changes: 16 additions & 0 deletions cli/cmd/generate_azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,22 @@ By default, this command will function interactively, prompting for the required
}
)

type AzureGenerateCommandExtraState struct {
Output string
TerraformApply bool
}

func (a *AzureGenerateCommandExtraState) isEmpty() bool {
return a.Output == "" && !a.TerraformApply
}

// Flush current state of the struct to disk, provided it's not empty
func (a *AzureGenerateCommandExtraState) writeCache() {
if !a.isEmpty() {
cli.WriteAssetToCache(CachedAzureAssetExtraState, time.Now().Add(time.Hour*1), a)
}
}

func validateStorageLocation(location string) error {
if !validStorageLocations[location] {
return errors.New("invalid storage location supplied")
Expand Down
25 changes: 25 additions & 0 deletions cli/cmd/generate_cloud_account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package cmd

import "github.com/spf13/cobra"

var (
generateCloudAccountCommand = &cobra.Command{
Use: "cloud-account",
Aliases: []string{"cloud", "ca"},
Short: "Generate Lacework integration IaC",
Long: "Generate Lacework integration IaC for cloud environment(s)",
}
)

func init() {
generateTfCommand.AddCommand(generateCloudAccountCommand)

// Uncomment when `cloud-account iac-generate` removed
// initGenerateAwsTfCommandFlags()
// initGenerateGcpTfCommandFlags()
// initGenerateAzureTfCommandFlags()

generateCloudAccountCommand.AddCommand(generateAwsTfCommand)
generateCloudAccountCommand.AddCommand(generateGcpTfCommand)
generateCloudAccountCommand.AddCommand(generateAzureTfCommand)
}
26 changes: 26 additions & 0 deletions cli/cmd/generate_gcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,32 @@ See help output for more details on the parameter value(s) required for Terrafor
}
)

type GcpGenerateCommandExtraState struct {
AskAdvanced bool
Output string
ConfigureNewBucketSettings bool
UseExistingServiceAccount bool
UseExistingBucket bool
UseExistingSink bool
TerraformApply bool
}

func (gcp *GcpGenerateCommandExtraState) isEmpty() bool {
return gcp.Output == "" &&
!gcp.AskAdvanced &&
!gcp.UseExistingServiceAccount &&
!gcp.UseExistingBucket &&
!gcp.UseExistingSink &&
!gcp.TerraformApply
}

// Flush current state of the struct to disk, provided it's not empty
func (gcp *GcpGenerateCommandExtraState) writeCache() {
if !gcp.isEmpty() {
cli.WriteAssetToCache(CachedAssetGcpExtraState, time.Now().Add(time.Hour*1), gcp)
}
}

func initGenerateGcpTfCommandFlags() {
// add flags to sub commands
// TODO Share the help with the interactive generation
Expand Down
50 changes: 25 additions & 25 deletions integration/aws_generation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ func TestGenerationAwsErrorOnNoSelection(t *testing.T) {
c.SendLine("n")
expectString(t, c, "ERROR collecting/confirming parameters: must enable cloudtrail or config")
},
"cloud",
"iac",
"generate",
"cloud-account",
"aws",
)
}
Expand All @@ -57,8 +57,8 @@ func TestGenerationAwsSimple(t *testing.T) {
c.SendLine("n")
final, _ = c.ExpectEOF()
},
"cloud",
"iac",
"generate",
"cloud-account",
"aws",
)

Expand Down Expand Up @@ -112,8 +112,8 @@ func TestGenerationAwsCustomizedOutputLocation(t *testing.T) {
c.SendLine("n")
final, _ = c.ExpectEOF()
},
"cloud",
"iac",
"generate",
"cloud-account",
"aws",
)

Expand Down Expand Up @@ -154,8 +154,8 @@ func TestGenerationAwsConfigOnly(t *testing.T) {
c.SendLine("n")
final, _ = c.ExpectEOF()
},
"cloud",
"iac",
"generate",
"cloud-account",
"aws",
)

Expand Down Expand Up @@ -199,8 +199,8 @@ func TestGenerationAwsAdvancedOptsDone(t *testing.T) {
c.SendLine("n")
final, _ = c.ExpectEOF()
},
"cloud",
"iac",
"generate",
"cloud-account",
"aws",
)

Expand Down Expand Up @@ -273,8 +273,8 @@ func TestGenerationAwsAdvancedOptsConsolidatedAndForceDestroy(t *testing.T) {
c.SendLine("n")
final, _ = c.ExpectEOF()
},
"cloud",
"iac",
"generate",
"cloud-account",
"aws",
)

Expand Down Expand Up @@ -343,8 +343,8 @@ func TestGenerationAwsAdvancedOptsUseExistingCloudtrail(t *testing.T) {
c.SendLine("n")
final, _ = c.ExpectEOF()
},
"cloud",
"iac",
"generate",
"cloud-account",
"aws",
)

Expand Down Expand Up @@ -437,8 +437,8 @@ func TestGenerationAwsAdvancedOptsConsolidatedWithSubAccounts(t *testing.T) {
c.SendLine("n")
final, _ = c.ExpectEOF()
},
"cloud",
"iac",
"generate",
"cloud-account",
"aws",
)

Expand Down Expand Up @@ -497,8 +497,8 @@ func TestGenerationAwsAdvancedOptsConfigWithSubAccounts(t *testing.T) {
c.SendLine("n")
final, _ = c.ExpectEOF()
},
"cloud",
"iac",
"generate",
"cloud-account",
"aws",
)

Expand Down Expand Up @@ -556,8 +556,8 @@ func TestGenerationAwsAdvancedOptsConsolidatedWithSubAccountsPassedByFlag(t *tes
c.SendLine("n")
final, _ = c.ExpectEOF()
},
"cloud",
"iac",
"generate",
"cloud-account",
"aws",
"--consolidated_cloudtrail",
"--aws_subaccount",
Expand Down Expand Up @@ -618,8 +618,8 @@ func TestGenerationAwsAdvancedOptsUseExistingIAM(t *testing.T) {
c.SendLine("n")
final, _ = c.ExpectEOF()
},
"generate",
"cloud-account",
"iac-generate",
"aws",
)

Expand Down Expand Up @@ -681,8 +681,8 @@ func TestGenerationAwsAdvancedOptsUseExistingElements(t *testing.T) {
c.SendLine("n")
final, _ = c.ExpectEOF()
},
"generate",
"cloud-account",
"iac-generate",
"aws",
)

Expand Down Expand Up @@ -762,8 +762,8 @@ func TestGenerationAwsAdvancedOptsCreateNewElements(t *testing.T) {
c.SendLine("n")
final, _ = c.ExpectEOF()
},
"generate",
"cloud-account",
"iac-generate",
"aws",
)

Expand Down Expand Up @@ -828,8 +828,8 @@ func TestGenerationAwsWithExistingTerraform(t *testing.T) {
expectString(t, c, fmt.Sprintf("%s/main.tf already exists, overwrite?", dir))
c.SendLine("n")
},
"cloud",
"iac",
"generate",
"cloud-account",
"aws",
)

Expand Down
Loading

0 comments on commit 56cbdcd

Please sign in to comment.