Skip to content

Commit

Permalink
zero apply context (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
thdaraujo committed Jun 10, 2020
1 parent 6799dc6 commit de27965
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 70 deletions.
76 changes: 6 additions & 70 deletions cmd/apply.go
@@ -1,16 +1,9 @@
package cmd

import (
"fmt"
"log"
"os/exec"
"path/filepath"
"strings"

"github.com/commitdev/zero/internal/config/projectconfig"
"github.com/commitdev/zero/internal/constants"
"github.com/commitdev/zero/internal/util"
"github.com/commitdev/zero/pkg/util/exit"
"github.com/manifoldco/promptui"
"github.com/commitdev/zero/internal/context"
"github.com/spf13/cobra"
)

Expand All @@ -29,68 +22,11 @@ var applyCmd = &cobra.Command{
Short: "Execute modules to create projects, infrastructure, etc.",
Run: func(cmd *cobra.Command, args []string) {

if len(applyEnvironments) == 0 {
fmt.Println(`Choose the environments to apply. This will create infrastructure, CI pipelines, etc.
At this point, real things will be generated that may cost money!
Only a single environment may be suitable for an initial test, but for a real system we suggest setting up both staging and production environments.`)
applyEnvironments = promptEnvironments()
}

// Strict for now, we can brainstorm how much we want to support custom environments later
for _, env := range applyEnvironments {
if env != "staging" && env != "production" {
exit.Fatal("The currently supported environments are \"staging\" and \"production\"")
}
}

// @TODO : Pass environments to make commands

var config interface{}
makeAll(config, applyEnvironments)
// @TODO where applyConfigPath comes from?
projectContext := context.Apply(applyEnvironments, applyConfigPath)
// @TODO rootdir or applyConfigPath?
projectconfig.Apply(projectconfig.RootDir, projectContext, applyEnvironments)
},
}

// promptEnvironments Prompts the user for the environments to apply against and returns a slice of strings representing the environments
func promptEnvironments() []string {
items := map[string][]string{
"Staging ": {"staging"},
"Production": {"production"},
"Both Staging and Production": {"staging", "production"},
}

var labels []string
for label := range items {
labels = append(labels, label)
}

providerPrompt := promptui.Select{
Label: "Environments",
Items: labels,
}
_, providerResult, err := providerPrompt.Run()
if err != nil {
log.Fatalf("Prompt failed %v\n", err)
panic(err)
}
return items[providerResult]
}

func makeAll(config interface{}, envars []string) error {
environmentArg := fmt.Sprintf("ENVIRONMENT=%s", strings.Join(envars, ","))
projects := projectPaths(config)

for _, project := range projects {
absPath, err := filepath.Abs(project)
if err != nil {
return err
}
output := util.ExecuteCommandOutput(exec.Command("make", environmentArg), absPath, envars)
fmt.Println(output)
}
return nil
}

// @TODO extract project paths from some config/yaml
func projectPaths(someConfig interface{}) []string {
return []string{"foo", "bar", "baz"}
}
46 changes: 46 additions & 0 deletions internal/config/projectconfig/apply.go
@@ -0,0 +1,46 @@
package projectconfig

import (
"fmt"
"os/exec"
"path"
"path/filepath"
"strings"

"github.com/commitdev/zero/internal/util"
"github.com/commitdev/zero/pkg/util/flog"
)

// Apply will bootstrap the runtime environment for the project
func Apply(dir string, projectContext *ZeroProjectConfig, applyEnvironments []string) {
flog.Infof(":tada: Bootstrapping project %s. Please use the zero.[hcl, yaml] file to modify the project as needed. %s.", projectContext.Name)

flog.Infof("Cloud provider: %s", "AWS") // will this come from the config?

flog.Infof("Runtime platform: %s", "Kubernetes")

flog.Infof("Infrastructure executor: %s", "Terraform")

// other details...

makeAll(dir, projectContext, applyEnvironments)
}

func makeAll(dir string, projectContext *ZeroProjectConfig, applyEnvironments []string) error {
environmentArg := fmt.Sprintf("ENVIRONMENT=%s", strings.Join(applyEnvironments, ","))
envars := []string{environmentArg}

for _, module := range projectContext.Modules {
// TODO what's the root dir for these modules?
// what's the real path to these modules? It's probably not the module name...
modulePath, err := filepath.Abs(path.Join(dir, projectContext.Name, module))
if err != nil {
return err
}

// @TODO mock exec?
output := util.ExecuteCommandOutput(exec.Command("make", environmentArg), modulePath, envars)
fmt.Println(output)
}
return nil
}
63 changes: 63 additions & 0 deletions internal/context/apply.go
@@ -0,0 +1,63 @@
package context

import (
"fmt"
"log"

"github.com/commitdev/zero/internal/config/projectconfig"
"github.com/commitdev/zero/pkg/util/exit"
"github.com/manifoldco/promptui"
)

// Apply will load the context/configuration to be used by the apply command
func Apply(applyEnvironments []string, applyConfigPath string) *projectconfig.ZeroProjectConfig {
if len(applyEnvironments) == 0 {
fmt.Println(`Choose the environments to apply. This will create infrastructure, CI pipelines, etc.
At this point, real things will be generated that may cost money!
Only a single environment may be suitable for an initial test, but for a real system we suggest setting up both staging and production environments.`)
applyEnvironments = promptEnvironments()
}

validateEnvironments(applyEnvironments)

if applyConfigPath == "" {
exit.Fatal("config path cannot be empty!")
}

projectConfig := projectconfig.LoadConfig(applyConfigPath)
return projectConfig
}

// promptEnvironments Prompts the user for the environments to apply against and returns a slice of strings representing the environments
func promptEnvironments() []string {
items := map[string][]string{
"Staging ": {"staging"},
"Production": {"production"},
"Both Staging and Production": {"staging", "production"},
}

var labels []string
for label := range items {
labels = append(labels, label)
}

providerPrompt := promptui.Select{
Label: "Environments",
Items: labels,
}
_, providerResult, err := providerPrompt.Run()
if err != nil {
log.Fatalf("Prompt failed %v\n", err)
panic(err)
}
return items[providerResult]
}

func validateEnvironments(applyEnvironments []string) {
// Strict for now, we can brainstorm how much we want to support custom environments later
for _, env := range applyEnvironments {
if env != "staging" && env != "production" {
exit.Fatal("The currently supported environments are \"staging\" and \"production\"")
}
}
}

0 comments on commit de27965

Please sign in to comment.