Skip to content

Commit

Permalink
PR feedback addressed
Browse files Browse the repository at this point in the history
- Decoupled bash reliance for template creation
- Tests updated and working
- Add ExpandHomeDir() and test
- Updated TestPathExistsInInventory to be more realistic
- Moved bash templates to their own directory
- Fixed pkg tests to specifications in PR
- Updated TemplateExists to support multiple inventoryPaths
  • Loading branch information
l50 committed Apr 28, 2023
1 parent 7da947a commit 4ca6a07
Show file tree
Hide file tree
Showing 11 changed files with 503 additions and 170 deletions.
87 changes: 48 additions & 39 deletions cmd/new.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ THE SOFTWARE.
package cmd

import (
"fmt"
"os"
"path/filepath"
"text/template"
Expand All @@ -28,6 +29,7 @@ import (
"github.com/facebookincubator/ttpforge/pkg/files"
"github.com/facebookincubator/ttpforge/pkg/logging"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.uber.org/zap"
)

Expand All @@ -37,7 +39,7 @@ func init() {
}

var newTTPInput NewTTPInput
var dirPath string
var ttpDir string

// NewTTPInput contains the inputs required to create a new TTP from a template.
type NewTTPInput struct {
Expand Down Expand Up @@ -72,24 +74,45 @@ func NewTTPBuilderCmd() *cobra.Command {
`,

PreRunE: func(cmd *cobra.Command, args []string) error {
if err := validateTemplateFlag(cmd); err != nil {
return err
}

requiredFlags := []string{
"template",
"path",
"ttp-type",
}

return checkRequiredFlags(cmd, requiredFlags)
for _, flag := range requiredFlags {
if err := cmd.MarkFlagRequired(flag); err != nil {
return err
}
}

return nil
},
Run: func(cmd *cobra.Command, args []string) {
inventoryPaths := viper.GetStringSlice("inventory")

var templatePath string

relTmplPath := filepath.Join("templates", newTTPInput.Template)

// Iterate through inventory paths and find the first matching template
for _, invPath := range inventoryPaths {
invPath = files.ExpandHomeDir(invPath)
absTemplatePath := filepath.Join(invPath, "..", relTmplPath)
templateFound, err := files.PathExistsInInventory(relTmplPath, []string{invPath})
cobra.CheckErr(err)

if templateFound {
templatePath = absTemplatePath
break
}
}

// Create the filepath for the input TTP if it doesn't already exist.
bashTTPFile := newTTPInput.Path
ttpFile := newTTPInput.Path

dirPath = filepath.Dir(bashTTPFile)
if err := files.CreateDirIfNotExists(dirPath); err != nil {
ttpDir = filepath.Dir(ttpFile)
if err := files.CreateDirIfNotExists(ttpDir); err != nil {
cobra.CheckErr(err)
}

Expand All @@ -98,9 +121,10 @@ func NewTTPBuilderCmd() *cobra.Command {
logging.Logger.Sugar().Errorw("failed to create TTP with:", newTTPInput, zap.Error(err))
cobra.CheckErr(err)
}

// Populate templated TTP file
tmpl := template.Must(
template.ParseFiles(filepath.Join("templates", "bashTTP.yaml.tmpl")))
template.ParseFiles(ttpFile))

yamlF, err := os.Create(newTTPInput.Path)
cobra.CheckErr(err)
Expand All @@ -110,10 +134,10 @@ func NewTTPBuilderCmd() *cobra.Command {
cobra.CheckErr(err)
}

// Create README from template
readme := filepath.Join(dirPath, "README.md")
// Create README from templae
readme := filepath.Join(ttpDir, "README.md")
tmpl = template.Must(
template.ParseFiles(filepath.Join("templates", "README.md.tmpl")))
template.ParseFiles(filepath.Join(templatePath, "README.md.tmpl")))

readmeF, err := os.Create(readme)
cobra.CheckErr(err)
Expand All @@ -123,17 +147,19 @@ func NewTTPBuilderCmd() *cobra.Command {
cobra.CheckErr(err)
}

// Create templated bash script (if applicable)
// Create templated file-based TTP (if applicable)
if newTTPInput.TTPType == "file" {
tmpl = template.Must(
template.ParseFiles(filepath.Join("templates", "bashTTP.sh.tmpl")))
if newTTPInput.Template == "bash" {
tmpl = template.Must(
template.ParseFiles(filepath.Join(templatePath, "bashTTP.sh.tmpl")))

bashScriptF, err := os.Create(filepath.Join(dirPath, "bashTTP.sh"))
cobra.CheckErr(err)
defer bashScriptF.Close()

if err := tmpl.Execute(bashScriptF, ttp); err != nil {
bashScriptF, err := os.Create(filepath.Join(ttpDir, "bashTTP.sh"))
cobra.CheckErr(err)
defer bashScriptF.Close()

if err := tmpl.Execute(bashScriptF, ttp); err != nil {
cobra.CheckErr(err)
}
}
}
},
Expand Down Expand Up @@ -162,7 +188,7 @@ func createTTP() (*blocks.TTP, error) {
if newTTPInput.TTPType == "file" {
step = blocks.NewFileStep()
step.(*blocks.FileStep).Act.Name = "example_file_step"
step.(*blocks.FileStep).FilePath = filepath.Join(dirPath, "bashTTP.sh")
step.(*blocks.FileStep).FilePath = filepath.Join(ttpDir, fmt.Sprintf("%sTTP.sh", newTTPInput.Template))
step.(*blocks.FileStep).Args = newTTPInput.Args
} else {
step = blocks.NewBasicStep()
Expand Down Expand Up @@ -196,20 +222,3 @@ func createTTP() (*blocks.TTP, error) {

return ttp, nil
}

func validateTemplateFlag(cmd *cobra.Command) error {
templateName, err := cmd.Flags().GetString("template")
if err != nil {
return err
}
exists, err := files.TemplateExists(templateName)
if err != nil {
logging.Logger.Sugar().Errorw("unsupported template:", templateName, zap.Error(err))
return err
}
if !exists {
logging.Logger.Sugar().Errorw("template not found:", templateName, zap.Error(err))
return err
}
return nil
}
Loading

0 comments on commit 4ca6a07

Please sign in to comment.