Skip to content

Commit

Permalink
Merge branch 'main' into davidgamero/bump-actions
Browse files Browse the repository at this point in the history
  • Loading branch information
davidgamero authored Mar 29, 2023
2 parents cee4520 + 7ddccbb commit 519fe38
Show file tree
Hide file tree
Showing 19 changed files with 1,232 additions and 475 deletions.
792 changes: 720 additions & 72 deletions .github/workflows/integration-linux.yml

Large diffs are not rendered by default.

131 changes: 80 additions & 51 deletions cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/manifoldco/promptui"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"golang.org/x/exp/maps"
"gopkg.in/yaml.v3"

"github.com/Azure/draft/pkg/config"
Expand All @@ -27,18 +28,21 @@ import (
// ErrNoLanguageDetected is raised when `draft create` does not detect source
// code for linguist to classify, or if there are no packs available for the detected languages.
var ErrNoLanguageDetected = errors.New("no supported languages were detected")
var flagVariablesMap = make(map[string]string)

const LANGUAGE_VARIABLE = "LANGUAGE"
const TWO_SPACES = " "

type createCmd struct {
appName string
lang string
dest string
appName string
lang string
dest string
deployType string

dockerfileOnly bool
deploymentOnly bool
skipFileDetection bool
flagVariables []string

createConfigPath string
createConfig *CreateConfig
Expand Down Expand Up @@ -70,9 +74,11 @@ func newCreateCmd() *cobra.Command {
f.StringVarP(&cc.appName, "app", "a", "", "specify the name of the helm release")
f.StringVarP(&cc.lang, "language", "l", "", "specify the language used to create the Kubernetes deployment")
f.StringVarP(&cc.dest, "destination", "d", ".", "specify the path to the project directory")
f.StringVarP(&cc.deployType, "deploy-type", "", ".", "specify deployement type (eg. helm, kustomize, manifests)")
f.BoolVar(&cc.dockerfileOnly, "dockerfile-only", false, "only create Dockerfile in the project directory")
f.BoolVar(&cc.deploymentOnly, "deployment-only", false, "only create deployment files in the project directory")
f.BoolVar(&cc.skipFileDetection, "skip-file-detection", false, "skip file detection step")
f.StringArrayVarP(&cc.flagVariables, "variable", "", []string{}, "pass additional variables using repeated --variable flag")

return cmd
}
Expand Down Expand Up @@ -101,6 +107,16 @@ func (cc *createCmd) initConfig() error {

func (cc *createCmd) run() error {
log.Debugf("config: %s", cc.createConfigPath)

for _, flagVar := range cc.flagVariables {
flagVarName, flagVarValue, ok := strings.Cut(flagVar, "=")
if !ok {
return fmt.Errorf("invalid variable format: %s", flagVar)
}
flagVariablesMap[flagVarName] = flagVarValue
log.Debugf("flag variable %s=%s", flagVarName, flagVarValue)
}

var dryRunRecorder *dryrunpkg.DryRunRecorder
if dryRun {
dryRunRecorder = dryrunpkg.NewDryRunRecorder()
Expand Down Expand Up @@ -142,53 +158,57 @@ func (cc *createCmd) detectLanguage() (*config.DraftConfig, string, error) {
var langs []*linguist.Language
var err error
if cc.createConfig.LanguageType == "" {
log.Info("--- Detecting Language ---")
langs, err = linguist.ProcessDir(cc.dest)
log.Debugf("linguist.ProcessDir(%v) result:\n\nError: %v", cc.dest, err)
if err != nil {
return nil, "", fmt.Errorf("there was an error detecting the language: %s", err)
}
for _, lang := range langs {
log.Debugf("%s:\t%f (%s)", lang.Language, lang.Percent, lang.Color)
// For now let's check here for weird stuff like go module support
if lang.Language == "Go" {
hasGo = true

selection := &promptui.Select{
Label: "Linguist detected Go, do you use Go Modules?",
Items: []string{"yes", "no"},
}

_, selectResponse, err := selection.Run()
if err != nil {
return nil, "", err
}

hasGoMod = strings.EqualFold(selectResponse, "yes")
if cc.lang != "" {
cc.createConfig.LanguageType = cc.lang
} else {
log.Info("--- Detecting Language ---")
langs, err = linguist.ProcessDir(cc.dest)
log.Debugf("linguist.ProcessDir(%v) result:\n\nError: %v", cc.dest, err)
if err != nil {
return nil, "", fmt.Errorf("there was an error detecting the language: %s", err)
}
for _, lang := range langs {
log.Debugf("%s:\t%f (%s)", lang.Language, lang.Percent, lang.Color)
// For now let's check here for weird stuff like go module support
if lang.Language == "Go" {
hasGo = true

selection := &promptui.Select{
Label: "Linguist detected Go, do you use Go Modules?",
Items: []string{"yes", "no"},
}

_, selectResponse, err := selection.Run()
if err != nil {
return nil, "", err
}

hasGoMod = strings.EqualFold(selectResponse, "yes")
}

if lang.Language == "Java" {
if lang.Language == "Java" {

selection := &promptui.Select{
Label: "Linguist detected Java, are you using maven or gradle?",
Items: []string{"gradle", "maven"},
}
selection := &promptui.Select{
Label: "Linguist detected Java, are you using maven or gradle?",
Items: []string{"gradle", "maven"},
}

_, selectResponse, err := selection.Run()
if err != nil {
return nil, "", err
}
_, selectResponse, err := selection.Run()
if err != nil {
return nil, "", err
}

if selectResponse == "gradle" {
lang.Language = "Gradle"
if selectResponse == "gradle" {
lang.Language = "Gradle"
}
}
}
}

log.Debugf("detected %d langs", len(langs))
log.Debugf("detected %d langs", len(langs))

if len(langs) == 0 {
return nil, "", ErrNoLanguageDetected
if len(langs) == 0 {
return nil, "", ErrNoLanguageDetected
}
}
}

Expand Down Expand Up @@ -231,7 +251,7 @@ func (cc *createCmd) generateDockerfile(langConfig *config.DraftConfig, lowerLan
var inputs map[string]string
var err error
if cc.createConfig.LanguageVariables == nil {
inputs, err = prompts.RunPromptsFromConfig(langConfig)
inputs, err = prompts.RunPromptsFromConfigWithSkips(langConfig, maps.Keys(flagVariablesMap))
if err != nil {
return err
}
Expand All @@ -248,6 +268,8 @@ func (cc *createCmd) generateDockerfile(langConfig *config.DraftConfig, lowerLan
}
}

maps.Copy(inputs, flagVariablesMap)

if err = cc.supportedLangs.CreateDockerfileForLanguage(lowerLang, inputs, cc.templateWriter); err != nil {
return fmt.Errorf("there was an error when creating the Dockerfile for language %s: %w", cc.createConfig.LanguageType, err)
}
Expand All @@ -262,6 +284,7 @@ func (cc *createCmd) createDeployment() error {
var deployType string
var customInputs map[string]string
var err error

if cc.createConfig.DeployType != "" {
deployType = strings.ToLower(cc.createConfig.DeployType)
deployConfig := d.GetConfig(deployType)
Expand All @@ -274,23 +297,29 @@ func (cc *createCmd) createDeployment() error {
}

} else {
selection := &promptui.Select{
Label: "Select k8s Deployment Type",
Items: []string{"helm", "kustomize", "manifests"},
}
if cc.deployType == "" {
selection := &promptui.Select{
Label: "Select k8s Deployment Type",
Items: []string{"helm", "kustomize", "manifests"},
}

_, deployType, err = selection.Run()
if err != nil {
return err
_, deployType, err = selection.Run()
if err != nil {
return err
}
} else {
deployType = cc.deployType
}

deployConfig := d.GetConfig(deployType)
customInputs, err = prompts.RunPromptsFromConfig(deployConfig)
customInputs, err = prompts.RunPromptsFromConfigWithSkips(deployConfig, maps.Keys(flagVariablesMap))
if err != nil {
return err
}
}

maps.Copy(customInputs, flagVariablesMap)

if cc.templateVariableRecorder != nil {
for k, v := range customInputs {
cc.templateVariableRecorder.Record(k, v)
Expand Down Expand Up @@ -419,7 +448,7 @@ func validateConfigInputsToPrompts(required []config.BuilderVar, provided []User

for _, variable := range required {
if _, ok := customInputs[variable.Name]; !ok {
return nil, fmt.Errorf("config missing language variable: %s with description: %s", variable.Name, variable.Description)
return nil, fmt.Errorf("config missing required variable: %s with description: %s", variable.Name, variable.Description)
}
}

Expand Down
98 changes: 83 additions & 15 deletions cmd/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"strings"
"testing"

Expand All @@ -21,15 +23,16 @@ func TestRun(t *testing.T) {
mockCC := &createCmd{}
mockCC.createConfig = &CreateConfig{}
mockCC.dest = "./.."
mockCC.createConfig.DeployType = "helm"
mockCC.createConfig.DeployType = ""
mockCC.createConfig.LanguageVariables = []UserInputs{}
mockCC.createConfig.DeployVariables = []UserInputs{}
mockPortInput := UserInputs{Name: "PORT", Value: "8080"}
mockAppNameInput := UserInputs{Name: "APPNAME", Value: "testingCreateCommand"}
mockCC.createConfig.DeployVariables = append(mockCC.createConfig.DeployVariables, mockPortInput, mockAppNameInput)
mockCC.createConfig.LanguageVariables = append(mockCC.createConfig.LanguageVariables, mockPortInput)
mockCC.templateWriter = &writers.LocalFSWriter{}

flagVariablesMap = map[string]string{"PORT": "8080", "APPNAME": "testingCreateCommand", "VERSION": "1.18", "SERVICEPORT": "8080", "NAMESPACE": "testNamespace", "IMAGENAME": "testImage", "IMAGETAG": "latest"}
deployTypes := []string{"helm", "kustomize", "manifests"}
oldDockerfile, _ := ioutil.ReadFile("./../Dockerfile")
oldDockerignore, _ := ioutil.ReadFile("./../.dockerignore")

Expand All @@ -42,8 +45,18 @@ func TestRun(t *testing.T) {
err = mockCC.generateDockerfile(detectedLang, lowerLang)
assert.True(t, err == nil)

err = mockCC.createDeployment()
//when language variables are passed in --variable flag
mockCC.createConfig.LanguageVariables = nil
mockCC.lang = "go"
detectedLang, lowerLang, err = mockCC.mockDetectLanguage()
assert.False(t, detectedLang == nil)
assert.False(t, lowerLang == "")
assert.True(t, err == nil)
err = mockCC.generateDockerfile(detectedLang, lowerLang)
println(err)
assert.True(t, err == nil)

//Write back old Dockerfile
err = ioutil.WriteFile("./../Dockerfile", oldDockerfile, 0644)
if err != nil {
t.Error(err)
Expand All @@ -54,7 +67,42 @@ func TestRun(t *testing.T) {
t.Error(err)
}

os.RemoveAll("./../charts")
for _, deployType := range deployTypes {
//deployment variables passed through --variable flag
mockCC.deployType = deployType
err = mockCC.createDeployment()
assert.True(t, err == nil)
//check if deployment files have been created
err, deploymentFiles := getAllDeploymentFiles(path.Join("../template/deployments", mockCC.deployType))
assert.Nil(t, err)
for _, fileName := range deploymentFiles {
_, err = os.Stat(fileName)
assert.True(t, err == nil)
}

os.RemoveAll("./../charts")
os.RemoveAll("./../base")
os.RemoveAll("./../overlays")
os.RemoveAll("./../manifests")

//deployment variables passed through createConfig
mockCC.createConfig.DeployType = deployType
err = mockCC.createDeployment()
assert.True(t, err == nil)
//check if deployment files have been created
err, deploymentFiles = getAllDeploymentFiles(path.Join("../template/deployments", mockCC.createConfig.DeployType))
assert.Nil(t, err)
for _, fileName := range deploymentFiles {
_, err = os.Stat(fileName)
assert.True(t, err == nil)
}
mockCC.createConfig.DeployType = ""

os.RemoveAll("./../charts")
os.RemoveAll("./../base")
os.RemoveAll("./../overlays")
os.RemoveAll("./../manifests")
}
}

func TestInitConfig(t *testing.T) {
Expand Down Expand Up @@ -106,20 +154,24 @@ func (mcc *createCmd) mockDetectLanguage() (*config.DraftConfig, string, error)
var err error

if mcc.createConfig.LanguageType == "" {
langs, err = linguist.ProcessDir(mcc.dest)
log.Debugf("linguist.ProcessDir(%v) result:\n\nError: %v", mcc.dest, err)
if err != nil {
return nil, "", fmt.Errorf("there was an error detecting the language: %s", err)
}
if mcc.lang != "" {
mcc.createConfig.LanguageType = mcc.lang
} else {
langs, err = linguist.ProcessDir(mcc.dest)
log.Debugf("linguist.ProcessDir(%v) result:\n\nError: %v", mcc.dest, err)
if err != nil {
return nil, "", fmt.Errorf("there was an error detecting the language: %s", err)
}

for _, lang := range langs {
log.Debugf("%s:\t%f (%s)", lang.Language, lang.Percent, lang.Color)
}
for _, lang := range langs {
log.Debugf("%s:\t%f (%s)", lang.Language, lang.Percent, lang.Color)
}

log.Debugf("detected %d langs", len(langs))
log.Debugf("detected %d langs", len(langs))

if len(langs) == 0 {
return nil, "", ErrNoLanguageDetected
if len(langs) == 0 {
return nil, "", ErrNoLanguageDetected
}
}
}

Expand Down Expand Up @@ -154,3 +206,19 @@ func (mcc *createCmd) mockDetectLanguage() (*config.DraftConfig, string, error)
}
return nil, "", ErrNoLanguageDetected
}

func getAllDeploymentFiles(src string) (error, []string) {
deploymentFiles := []string{}
err := filepath.Walk(src,
func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
filePath := strings.ReplaceAll(path, src, "./..")
if info.Name() != "draft.yaml" {
deploymentFiles = append(deploymentFiles, filePath)
}
return nil
})
return err, deploymentFiles
}
Loading

0 comments on commit 519fe38

Please sign in to comment.