Skip to content

Commit

Permalink
code cb
Browse files Browse the repository at this point in the history
  • Loading branch information
WillBeebe committed Jul 5, 2024
1 parent 588fe12 commit 4d83286
Show file tree
Hide file tree
Showing 7 changed files with 394 additions and 0 deletions.
2 changes: 2 additions & 0 deletions ada.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name: ada-cli
type: go
26 changes: 26 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,44 @@ require (
)

require (
dario.cat/mergo v1.0.0 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/ProtonMail/go-crypto v1.0.0 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/lipgloss v0.11.0 // indirect
github.com/charmbracelet/x/ansi v0.1.1 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.5.0 // indirect
github.com/go-git/go-git/v5 v5.12.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/osteele/liquid v1.4.0 // indirect
github.com/osteele/tuesday v1.0.3 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/skeema/knownhosts v1.2.2 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/image v0.15.0 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.22.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/term v0.21.0 // indirect
golang.org/x/tools v0.13.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
99 changes: 99 additions & 0 deletions go.sum

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions internal/cache/cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package cache

import (
"os"
"os/user"
"path/filepath"
)

func Dir() string {
dir, err := cacheDir()
if err != nil {
panic(err)
}
return dir
}

func cacheDir() (string, error) {
usr, _ := user.Current()
dir := usr.HomeDir
cacheDir := filepath.Join(dir, ".ada")
if _, err := os.Stat(cacheDir); !os.IsNotExist(err) {
return cacheDir, err
}

if errMkdir := os.Mkdir(cacheDir, 0755); errMkdir != nil {
return cacheDir, errMkdir
}
return cacheDir, nil
}
116 changes: 116 additions & 0 deletions internal/cache/templates.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package cache

import (
"fmt"
"io/ioutil"
"os"
"os/user"
"path/filepath"

"github.com/container-labs/ada/internal/common"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
)

const SoyTemplatesRepository = "ssh://github.com:7999/gst/ada-templates.git"

// const SoyTemplatesRepository = "https://github.com/massdriver-cloud/application-templates"

var logger = common.Logger()

// TemplateCacheDir is a reader function to access the local cache of templates.
// When developing templates, the cache source can be overwritten for reads by setting `MD_DEV_TEMPLATES_PATH`
func TemplateCacheDir() string {
var templatesPath string
localDevTemplatesPath := os.Getenv("ada_DEV_TEMPLATES_PATH")
if localDevTemplatesPath == "" {
dir, _ := templateCacheDir()
templatesPath = dir
} else {
logger.Info(fmt.Sprintf("Reading templates for local development path: %s", localDevTemplatesPath))
templatesPath = localDevTemplatesPath
}

return templatesPath
}

func Templates() ([]string, error) {
templates := []string{}
templateDirs, err := ioutil.ReadDir(TemplateCacheDir())
if err != nil {
return templates, err
}

for _, f := range templateDirs {
// all directories that aren't .git
// cheap way of listing templates
if f.IsDir() && f.Name() != ".git" {
templates = append(templates, f.Name())
}
}
return templates, nil
}

func RefreshTemplates() error {
if err := clearTemplateCache(); err != nil {
return err
}
return downloadTemplates()
}

// templateCacheDir is the actual cache directory. This should be used internally when managing
// files so that development template directories aren't overwritten on accident.
func templateCacheDir() (string, error) {
cacheDir, err := cacheDir()
if err != nil {
return "", err
}

templateDir := filepath.Join(cacheDir, "templates")
if _, errDir := os.Stat(templateDir); !os.IsNotExist(errDir) {
return templateDir, errDir
}

if errMkdir := os.Mkdir(templateDir, 0755); errMkdir != nil {
return templateDir, errMkdir
}
return templateDir, nil
}

func clearTemplateCache() error {
templateCacheDir, _ := templateCacheDir()
if err := os.RemoveAll(templateCacheDir); err != nil {
return err
}
return nil
}

func downloadTemplates() error {
templateCacheDir, _ := templateCacheDir()
// log.Debug().Msgf("Downloading templates to %s", templateCacheDir)

// begin: remove for public repo
usr, err := user.Current()
if err != nil {
return err
}
homeDir := usr.HomeDir

var publicKeys *ssh.PublicKeys
publicKeys, err = ssh.NewPublicKeysFromFile("git", filepath.Join(homeDir, ".ssh/id_ed25519"), "")
if err != nil {
return err
}
// end: remove for public repo

_, cloneErr := git.PlainClone(templateCacheDir, false, &git.CloneOptions{
URL: SoyTemplatesRepository,
Auth: publicKeys,
// Progress: os.Stdout,
Depth: 1,
})
if cloneErr != nil {
return cloneErr
}
return nil
}
23 changes: 23 additions & 0 deletions internal/template/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package template

import (
"fmt"
"strings"

"github.com/container-labs/ada/internal/cache"
"github.com/container-labs/ada/internal/common"
)

var logger = common.Logger()

func List() error {
templates, err := cache.Templates()

if err != nil {
return err
}

logger.Info(fmt.Sprintf("Templates:\n %s\n", strings.Join(templates, "\n ")))

return nil
}
99 changes: 99 additions & 0 deletions internal/template/render.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package template

import (
"bytes"
"errors"
"fmt"
"os"

jsoniter "github.com/json-iterator/go"
"github.com/osteele/liquid"
)

type RenderData struct {
Name string `json:"name"`
Type string `json:"type"`
OutputDir string
}

func Render(templateDir string, data *RenderData) error {
// templateDir := fmt.Sprintf("%s/%s", cache.TemplateCacheDir(), "helm-chart")
fmt.Println(data)

files, readDirErr := os.ReadDir(templateDir)
if readDirErr != nil {
return readDirErr
}

if _, checkDirExistsErr := os.Stat(data.OutputDir); errors.Is(checkDirExistsErr, os.ErrNotExist) {
mkdirErr := os.MkdirAll(data.OutputDir, os.ModePerm)
if mkdirErr != nil {
return mkdirErr
}
}

for _, file := range files {
srcPath := templateDir + "/" + file.Name()
destPath := data.OutputDir + "/" + file.Name()

if _, err := os.Stat(destPath); err == nil {
fmt.Printf("%s exists. Overwrite? (y|N): ", destPath)
var response string
fmt.Scanln(&response)

if response != "y" && response != "Y" && response != "yes" {
continue
}
}

if file.IsDir() {
dataCopy := RenderData{}
// copy(dataCopy, data)
// TODO: better copy
dataCopy.Name = data.Name
dataCopy.OutputDir = fmt.Sprintf("%s/%s", data.OutputDir, file.Name())

errRender := Render(fmt.Sprintf("%s/%s", templateDir, file.Name()), &dataCopy)
if errRender != nil {
return errRender
}
} else {

contents, err := os.ReadFile(srcPath)
if err != nil {
return err
}

err = WriteToFile(destPath, contents, data)
if err != nil {
return err
}
}
}

return nil
}

func WriteToFile(filePath string, template []byte, data *RenderData) error {
var json = jsoniter.ConfigCompatibleWithStandardLibrary
engine := liquid.NewEngine()

var bindings map[string]interface{}
inrec, errMarshal := json.Marshal(data)
if errMarshal != nil {
return errMarshal
}
json.Unmarshal(inrec, &bindings)

out, renderErr := engine.ParseAndRender(template, bindings)
if renderErr != nil {
return renderErr
}

// hack hack hack
// find-replace { { with {{ and } } with }}
newSlice := bytes.Replace(out, []byte("{ {"), []byte("{{"), -1)
lastSlice := bytes.Replace(newSlice, []byte("} }"), []byte("}}"), -1)

return os.WriteFile(filePath, lastSlice, 0600)
}

0 comments on commit 4d83286

Please sign in to comment.