Skip to content

Commit

Permalink
alpha: support for cloudflare functions and docker production mode
Browse files Browse the repository at this point in the history
  • Loading branch information
23doors committed Sep 7, 2022
1 parent ee0014e commit a6d07d2
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 88 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,14 @@ require (
github.com/docker/docker v20.10.17+incompatible
github.com/enescakir/emoji v1.0.0
github.com/go-ozzo/ozzo-validation/v4 v4.3.0
github.com/gobwas/glob v0.2.3
github.com/google/go-github/v35 v35.3.0
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/gookit/color v1.5.0
github.com/goreleaser/fileglob v1.3.0
github.com/mholt/archiver/v3 v3.5.1
github.com/mitchellh/go-homedir v1.1.0
github.com/otiai10/copy v1.7.0
github.com/outblocks/outblocks-plugin-go v0.0.0-20220818132903-e1628dcab8fb
github.com/outblocks/outblocks-plugin-go v0.0.0-20220905223714-aedc83d026a3
github.com/pkg/errors v0.9.1
github.com/pterm/pterm v0.12.41
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0
Expand Down Expand Up @@ -51,6 +50,7 @@ require (
github.com/fatih/color v1.13.0 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/go-playground/validator/v10 v10.11.0 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,8 @@ github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
github.com/otiai10/mint v1.3.3 h1:7JgpsBaN0uMkyju4tbYHu0mnM55hNKVYLsXmwr15NQI=
github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
github.com/outblocks/outblocks-plugin-go v0.0.0-20220818132903-e1628dcab8fb h1:yr1vjWlH6St2YmiRjZ4oBHsao97Nj6xYQ5Jd6vJEBQQ=
github.com/outblocks/outblocks-plugin-go v0.0.0-20220818132903-e1628dcab8fb/go.mod h1:avN1f+Lp4odkiQ1k7hDi5IyrC67rCyrWu8nqTIQv46M=
github.com/outblocks/outblocks-plugin-go v0.0.0-20220905223714-aedc83d026a3 h1:uD6loiLycL81NILu50HS/m3x8yPBZrUO1LYRjT211Yo=
github.com/outblocks/outblocks-plugin-go v0.0.0-20220905223714-aedc83d026a3/go.mod h1:qnYZnWLB75EQVvcinZtah7p7eAov7UUUBHcDBq3xZ28=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
Expand Down
76 changes: 5 additions & 71 deletions internal/fileutil/zip.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,49 +7,10 @@ import (
"path/filepath"
"time"

"github.com/ansel1/merry/v2"
"github.com/gobwas/glob"
plugin_util "github.com/outblocks/outblocks-plugin-go/util"
)

func CheckMatch(name string, globs []glob.Glob) bool {
for _, g := range globs {
if g.Match(name) {
return true
}
}

return false
}

func ArchiveDir(dir, out string, excludes []string) error {
for i := range excludes {
excludes[i] = filepath.FromSlash(excludes[i])
}

var (
g glob.Glob
excludeGlobs, includeGlobs []glob.Glob
err error
)

for _, pat := range excludes {
if len(pat) > 0 && pat[0] == '!' {
g, err = glob.Compile(pat[1:])
if err != nil {
return merry.Errorf("unable to parse inclusion '%s': %w", pat, err)
}

excludeGlobs = append(excludeGlobs, g)
} else {
g, err = glob.Compile(pat)
if err != nil {
return merry.Errorf("unable to parse exclusion '%s': %w", pat, err)
}

includeGlobs = append(includeGlobs, g)
}
}

f, err := os.Create(out)
if err != nil {
return err
Expand All @@ -60,41 +21,12 @@ func ArchiveDir(dir, out string, excludes []string) error {
w := zip.NewWriter(f)
defer w.Close()

return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return fmt.Errorf("error encountered during file walk: %s", err)
}

relname, err := filepath.Rel(dir, path)
if err != nil {
return fmt.Errorf("error relativizing file for archival: %s", err)
}

isMatch := CheckMatch(relname, excludeGlobs)
if isMatch && CheckMatch(relname, includeGlobs) {
isMatch = false
}

if info.IsDir() {
if isMatch {
return filepath.SkipDir
}
return nil
}

if isMatch {
return nil
}

if err != nil {
return err
}

return plugin_util.WalkWithExclusions(dir, excludes, func(path, rel string, info os.FileInfo) error {
fh, err := zip.FileInfoHeader(info)
if err != nil {
return fmt.Errorf("error creating file header: %s", err)
}
fh.Name = filepath.ToSlash(relname)
fh.Name = filepath.ToSlash(rel)
fh.Method = zip.Deflate
// fh.Modified alone isn't enough when using a zero value
fh.SetModTime(time.Time{}) //nolint
Expand All @@ -107,7 +39,9 @@ func ArchiveDir(dir, out string, excludes []string) error {
if err != nil {
return fmt.Errorf("error reading file for archival: %s", err)
}

_, err = f.Write(content)

return err
})
}
2 changes: 1 addition & 1 deletion pkg/actions/apps_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ func (m *AppManager) promptAddFunction(opts *AppAddOptions) (*functionAppInfo, e
if opts.FunctionRuntime == "" {
qs = append(qs, &survey.Question{
Name: "FunctionRuntime",
Prompt: &survey.Input{Message: "Function runtime (the runtime in which the function is going to run):"},
Prompt: &survey.Input{Message: "Function runtime (the runtime in which the function is going to run - if deployment plugin supports multiple runtimes):"},
})
} else {
m.log.Printf("%s %s\n", pterm.Bold.Sprint("Function runtime:"), pterm.Cyan(opts.FunctionRuntime))
Expand Down
10 changes: 10 additions & 0 deletions pkg/actions/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,8 @@ func computeDomainsInfo(cfg *config.Project, state *statefile.StateData) []*apiv
if r.DnsPlugin == "" {
r.DnsPlugin = plug
}

r.AppIds = nil
}

var missingHosts []string
Expand All @@ -575,6 +577,10 @@ func computeDomainsInfo(cfg *config.Project, state *statefile.StateData) []*apiv
continue
}

if cfg.AppByID(app.App.Id) != nil {
continue
}

u, _ := config.ParseURL(app.App.Url, false)
if u == nil {
continue
Expand All @@ -590,6 +596,8 @@ func computeDomainsInfo(cfg *config.Project, state *statefile.StateData) []*apiv
continue
}

match.AppIds = append(match.AppIds, app.App.Id)

if _, ok := m[match]; ok {
continue
}
Expand All @@ -615,6 +623,8 @@ func computeDomainsInfo(cfg *config.Project, state *statefile.StateData) []*apiv
continue
}

match.AppIds = append(match.AppIds, app.ID())

if _, ok := m[match]; ok {
continue
}
Expand Down
31 changes: 29 additions & 2 deletions pkg/actions/deploy_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,15 +214,42 @@ func (d *Deploy) buildServiceApp(ctx context.Context, app *config.ServiceApp, ev
}

func (d *Deploy) buildFunctionApp(ctx context.Context, app *config.FunctionApp, eval *util.VarEvaluator) error {
var err error

if !app.Build.Command.IsEmpty() {
env := plugin_util.MergeStringMaps(app.Env(), app.Build.Env)

env, err = eval.ExpandStringMap(env)
if err != nil {
return err
}

cmd, err := command.New(app.Build.Command.ExecCmdAsUser(), command.WithDir(app.Dir()), command.WithEnv(util.FlattenEnvMap(env)))
if err != nil {
return merry.Errorf("error preparing build command for %s app: %s: %w", app.Type(), app.Name(), err)
}

err = d.runAppCommand(ctx, cmd, app)
if err != nil {
return err
}
}

// Archive if necessary.
archive := app.DeployPlugin().AppOverrides.Function.Archive
if archive != nil && !*archive {
return nil
}

out := filepath.Join(d.opts.BuildCacheDir, fmt.Sprintf("%s.zip", app.ID()))

patterns := []string{
"{*.outblocks.yaml,*.outblocks.yml,outblocks.yaml,outblocks.yml,.git,.gitignore,.DS_Store,npm-debug.log}",
"{*.outblocks.yaml,*.outblocks.yml,outblocks.yaml,outblocks.yml,.git,.gitignore,.DS_Store,node_modules,npm-debug.log}",
}

patterns = append(patterns, app.Package.Patterns...)

err := fileutil.ArchiveDir(app.Dir(), out, patterns)
err = fileutil.ArchiveDir(app.Dir(), out, patterns)
if err != nil {
return merry.Errorf("error creating archive for %s app: %s: %w", app.Type(), app.Name(), err)
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/actions/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,12 +188,12 @@ func (d *Run) prepareRunApps(info *runInfo, cfg *config.Project, ports map[int]s
}

for _, app := range apps {
if app.RunInfo().Command.IsEmpty() {
runInfo := app.RunInfo()

if runInfo.Plugin == config.RunPluginDirect && runInfo.Command.IsEmpty() {
return app.YAMLError("$.run.command", "run.command is required to run app")
}

runInfo := app.RunInfo()

appPort := runInfo.Port
if appPort == 0 {
appPort = grabPort(ports, port)
Expand Down
2 changes: 1 addition & 1 deletion pkg/config/project_normalization.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func (p *Project) Normalize() error {
if app.URL() != nil {
url := app.URL().String()
if cur, ok := urlMap[url]; ok {
return merry.Errorf("same URL '%s' used in more than 1 app: '%s' and '%s'", url, app.Name(), cur.Name())
return merry.Errorf("same URL '%s' used in more than 1 app: %s '%s' and %s '%s'", url, app.Type(), app.Name(), cur.Type(), cur.Name())
}

urlMap[url] = app
Expand Down
7 changes: 7 additions & 0 deletions pkg/plugins/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type Plugin struct {
SupportedTypes []*PluginType `json:"supported_types"`
Commands map[string]*PluginCommand `json:"commands"`
SecretsRepr yaml.MapSlice `json:"secrets"`
AppOverrides AppOverrides `json:"app_overrides"`

Dir string `json:"-"`
CacheDir string `json:"-"`
Expand Down Expand Up @@ -60,6 +61,12 @@ const (

const DefaultPriority = 1000

type AppOverrides struct {
Function struct {
Archive *bool `json:"archive"`
} `json:"function"`
}

type PluginSecret struct {
Key string `json:"-"`
Description string `json:"description"`
Expand Down
40 changes: 36 additions & 4 deletions schema/schema-app.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,7 @@
},
"then": {
"required": [
"type",
"runtime"
"type"
],
"properties": {
"private": {
Expand All @@ -150,7 +149,7 @@
"type": "string"
},
"entrypoint": {
"description": "Name of the function that will be executed when the function is triggered. Defaults to application name.",
"description": "Name of the function that will be executed when the function is triggered. Not all deployment plugins support it. Defaults to application name.",
"type": "string"
},
"build": {
Expand Down Expand Up @@ -243,6 +242,13 @@
"timeout": {
"description": "Execution timeout. Execution is considered failed and can be terminated if the function is not completed at the end of the timeout period.",
"type": "integer"
},
"patterns": {
"description": "File/dir patterns to exclude (or force include if starts with '!').",
"type": "array",
"items": {
"type": "string"
}
}
}
},
Expand Down Expand Up @@ -434,7 +440,33 @@
"title": "Build function app",
"type": "object",
"additionalProperties": false,
"properties": {}
"properties": {
"env": {
"description": "Additional environment variables available during build.",
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"command": {
"description": "Command to be run to generate output files.",
"oneOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "string"
}
}
]
},
"dir": {
"description": "Output dir to where static files end up.",
"type": "string"
}
}
},
"ServiceContainer": {
"title": "Service app container definition",
Expand Down
3 changes: 2 additions & 1 deletion templates/app-function.yaml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@

# Name of the app.
name: {{.App.Name}}
{{- if .App.Runtime }}

# The runtime in which the function is going to run, refer to cloud provider docs for possible options.
runtime: {{.App.Runtime}}

{{ end }}
# Name of the function that will be executed when the function is triggered.
entrypoint: {{.App.Entrypoint}}

Expand Down
2 changes: 1 addition & 1 deletion templates/app-static.yaml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ path_redirect: /
# If app is not meant to be accessible without auth, mark it as private.
# private: true

# Build defines where static files are stored and optionally which command should be used to generate them.
# Build optionally defines where static files are stored and optionally which command should be used to generate them.
build:
{{- if .App.Build.Command }}
# Optional command to be run to generate output files.
Expand Down

0 comments on commit a6d07d2

Please sign in to comment.