Skip to content

Commit

Permalink
Refactor commands
Browse files Browse the repository at this point in the history
  • Loading branch information
djelusic committed Jul 12, 2021
1 parent 6fab6f5 commit 31bfafc
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 193 deletions.
111 changes: 57 additions & 54 deletions cmd/mantil/cmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"net/http"
"os"
"path"
"path/filepath"
"strings"
"text/template"

Expand All @@ -22,6 +21,50 @@ import (
"github.com/spf13/cobra"
)

func createProject(name, funcsPath string) mantil.Project {
project := mantil.NewProject(name)
files, err := ioutil.ReadDir(funcsPath)
if err != nil {
log.Fatal(err)
}
// go through functions in functions directory
for _, f := range files {
if !f.IsDir() {
continue
}
name := f.Name()
f := mantil.Function{
Path: name,
Name: name,
S3Key: fmt.Sprintf("functions/%s.zip", name),
Runtime: "go1.x",
MemorySize: 128,
Timeout: 60 * 15,
Handler: name,
}
f.URL = fmt.Sprintf("https://%s/%s/%s", project.Organization.DNSZone, project.Name, f.Path)
project.Functions = append(project.Functions, f)
}
return project
}

func renderTerraformTemplate(path string, project mantil.Project) error {
funcs := template.FuncMap{"join": strings.Join}
tfTpl, err := assets.Asset("terraform/templates/main.tf")
if err != nil {
return err
}
tpl := template.Must(template.New("").Funcs(funcs).Parse(string(tfTpl)))
buf := bytes.NewBuffer(nil)
if err := tpl.Execute(buf, project); err != nil {
return err
}
if err := ioutil.WriteFile(path, buf.Bytes(), 0644); err != nil {
return err
}
return nil
}

// deployCmd represents the deploy command
var deployCmd = &cobra.Command{
Use: "deploy",
Expand All @@ -33,78 +76,32 @@ var deployCmd = &cobra.Command{
http.ListenAndServe(":8080", mux)
}()

projectRoot, err := os.Getwd()
if err != nil {
log.Fatal(err)
}

projectName := path.Base(projectRoot)
project := mantil.NewProject(projectName)

awsClient, err := aws.New()
if err != nil {
log.Fatalf("error while initialising aws - %v", err)
}

files, err := ioutil.ReadDir(filepath.Join(projectRoot, "functions"))
projectRoot, err := os.Getwd()
if err != nil {
log.Fatal(err)
}

// go through functions in functions directory
for _, f := range files {
if !f.IsDir() {
continue
}
name := f.Name()
projectName := path.Base(projectRoot)
project := createProject(projectName, "functions")
for _, f := range project.Functions {
name := f.Name
log.Printf("deploying function %s", name)

funcDir := filepath.Join(projectRoot, "functions", name)
funcDir := fmt.Sprintf("functions/%s", name)
if err := shell.Exec([]string{"env", "GOOS=linux", "GOARCH=amd64", "go", "build", "-o", name}, funcDir); err != nil {
log.Fatalf("skipping function %s due to error while building binary - %v", name, err)
}

buf, err := createZipFunction(fmt.Sprintf("%s/%s", funcDir, name), name)
if err != nil {
log.Fatal(err)
}

f := mantil.Function{
Path: name,
Name: name,
S3Key: fmt.Sprintf("functions/%s.zip", name),
Runtime: "go1.x",
MemorySize: 128,
Timeout: 60 * 15,
Handler: name,
}
f.URL = fmt.Sprintf("https://%s/%s/%s", project.Organization.DNSZone, project.Name, f.Path)

if err := awsClient.PutObjectToS3Bucket(project.Bucket, f.S3Key, bytes.NewReader(buf)); err != nil {
log.Fatalf("error while uploading function %s to S3 - %v", f.Name, err)
}
defer func(f mantil.Function) {
lambdaName := fmt.Sprintf("%s-mantil-team-%s-%s", project.Organization.Name, project.Name, f.Name)
if err := awsClient.UpdateLambdaFunctionCodeFromS3(lambdaName, project.Bucket, f.S3Key); err != nil {
log.Fatal(err)
}
}(f)

project.Functions = append(project.Functions, f)
}
funcs := template.FuncMap{"join": strings.Join}
tfTpl, err := assets.Asset("terraform/templates/main.tf")
if err != nil {
log.Fatal(err)
}
tpl := template.Must(template.New("").Funcs(funcs).Parse(string(tfTpl)))
buf := bytes.NewBuffer(nil)
if err := tpl.Execute(buf, project); err != nil {
log.Fatal(err)
}
if err := ioutil.WriteFile("main.tf", buf.Bytes(), 0644); err != nil {
log.Fatal(err)
}
renderTerraformTemplate("main.tf", project)
tf := terraform.New(".")
if err := tf.Init(); err != nil {
log.Fatal(err)
Expand All @@ -115,6 +112,12 @@ var deployCmd = &cobra.Command{
if err := tf.Apply(false); err != nil {
log.Fatal(err)
}
for _, f := range project.Functions {
lambdaName := fmt.Sprintf("%s-mantil-team-%s-%s", project.Organization.Name, project.Name, f.Name)
if err := awsClient.UpdateLambdaFunctionCodeFromS3(lambdaName, project.Bucket, f.S3Key); err != nil {
log.Fatal(err)
}
}
},
}

Expand Down
10 changes: 10 additions & 0 deletions cmd/mantil/cmd/destroy.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package cmd
import (
"fmt"
"log"
"net/http"
"os"

"github.com/atoz-technology/mantil-cli/internal/assets"
"github.com/atoz-technology/mantil-cli/internal/aws"
"github.com/atoz-technology/mantil-cli/internal/github"
"github.com/atoz-technology/mantil-cli/internal/terraform"
Expand All @@ -17,10 +19,18 @@ var destroyCmd = &cobra.Command{
Use: "destroy",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
go func() {
mux := http.NewServeMux()
mux.Handle("/", http.FileServer(assets.AssetFile()))
http.ListenAndServe(":8080", mux)
}()
name := args[0]
_, err := os.Stat(name)
if err == nil {
fmt.Println("Destroying infrastructure...")
templatePath := fmt.Sprintf("%s/main.tf", name)
funcsPath := fmt.Sprintf("%s/functions", name)
renderTerraformTemplate(templatePath, createProject(name, funcsPath))
tf := terraform.New(name)
if err := tf.Init(); err != nil {
log.Fatal(err)
Expand Down
143 changes: 9 additions & 134 deletions cmd/mantil/cmd/init.go
Original file line number Diff line number Diff line change
@@ -1,154 +1,22 @@
package cmd

import (
"fmt"
"io/fs"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"

"github.com/atoz-technology/mantil-cli/internal/assets"
"github.com/atoz-technology/mantil-cli/internal/aws"
"github.com/atoz-technology/mantil-cli/internal/github"
"github.com/atoz-technology/mantil-cli/pkg/mantil"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
)

const templateRepo = "github.com/atoz-technology/go-mantil-template"

func replaceImportPaths(projectDir string, repoURL string) error {
repoURL = strings.ReplaceAll(repoURL, "https://", "")
return filepath.Walk(projectDir, func(path string, info fs.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
n := info.Name()
if strings.HasSuffix(n, ".go") || strings.HasSuffix(n, ".mod") {
fbuf, err := ioutil.ReadFile(path)
if err != nil {
return err
}
new := strings.ReplaceAll(string(fbuf), templateRepo, repoURL)
err = ioutil.WriteFile(path, []byte(new), 0)
if err != nil {
return err
}
}
return nil
})
}

func addGithubWorkflow(projectPath string) error {
destFolder := fmt.Sprintf("%s/.github/workflows", projectPath)
err := os.MkdirAll(destFolder, os.ModePerm)
if err != nil {
return err
}
workflow, err := assets.Asset("github/mantil-workflow.yml")
if err != nil {
return err
}
err = ioutil.WriteFile(fmt.Sprintf("%s/mantil-workflow.yml", destFolder), workflow, 0644)
if err != nil {
return err
}
return nil
}

func createRepoFromTemplate(projectName string, awsClient *aws.AWS) error {
githubClient, err := github.NewClient()
if err != nil {
return err
}
repoURL, err := githubClient.CreateRepo(projectName, "", true)
if err != nil {
return err
}
awsCredentials, err := awsClient.Credentials()
if err != nil {
return err
}
if err := githubClient.AddSecret(projectName, "AWS_ACCESS_KEY_ID", awsCredentials.AccessKeyID); err != nil {
return err
}
if err := githubClient.AddSecret(projectName, "AWS_SECRET_ACCESS_KEY", awsCredentials.SecretAccessKey); err != nil {
return err
}
templateUrl := fmt.Sprintf("https://%s.git", templateRepo)
_, err = git.PlainClone(projectName, false, &git.CloneOptions{
URL: templateUrl,
Progress: os.Stdout,
Depth: 1,
})
if err != nil {
return err
}
err = os.RemoveAll(fmt.Sprintf("%s/.git", projectName))
if err != nil {
return err
}
repo, err := git.PlainInit(projectName, false)
if err != nil {
return err
}
wt, err := repo.Worktree()
if err != nil {
return err
}
err = replaceImportPaths(projectName, repoURL)
if err != nil {
return err
}
err = addGithubWorkflow(projectName)
if err != nil {
return err
}
err = wt.AddGlob(".")
if err != nil {
return err
}
_, err = wt.Commit("initial commit", &git.CommitOptions{})
if err != nil {
return err
}
remoteName := "origin"
remote, err := repo.CreateRemote(&config.RemoteConfig{
Name: remoteName,
URLs: []string{repoURL},
})
if err != nil {
return err
}
err = remote.Push(&git.PushOptions{
RemoteName: remoteName,
Auth: &http.BasicAuth{
Username: "mantil",
Password: githubClient.Token,
},
})
if err != nil {
return err
}
return nil
}

// initCmd represents the init command
var initCmd = &cobra.Command{
Use: "init",
Short: "Initializes a mantil project",
Run: func(cmd *cobra.Command, args []string) {
namePrompt := promptui.Prompt{
Label: "Project name",
Default: "test",
Label: "Project name",
}
projectName, err := namePrompt.Run()
if err != nil {
Expand All @@ -170,10 +38,17 @@ var initCmd = &cobra.Command{
if err != nil {
log.Fatal(err)
}
err = createRepoFromTemplate(project.Name, aws)
githubClient, err := github.NewClient()
if err != nil {
log.Fatal(err)
}
templateRepo := "https://github.com/atoz-technology/go-mantil-template"
if err := githubClient.CreateRepoFromTemplate(templateRepo, projectName); err != nil {
log.Fatal(err)
}
if err := githubClient.AddAWSSecrets(projectName, aws); err != nil {
log.Fatal(err)
}
},
}

Expand Down
4 changes: 2 additions & 2 deletions internal/assets/bindata.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 31bfafc

Please sign in to comment.