Skip to content

Commit 4de9c71

Browse files
committed
feat: Cleanup functions start.
1 parent e0bfe0b commit 4de9c71

File tree

3 files changed

+187
-42
lines changed

3 files changed

+187
-42
lines changed

pkg/cmd/run/root.go

Lines changed: 7 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,10 @@ import (
2121
"os"
2222
"os/signal"
2323
"path/filepath"
24-
"runtime"
2524
"syscall"
2625
"time"
2726

28-
"github.com/docker/docker/api/types/container"
29-
"github.com/docker/docker/api/types/mount"
30-
"github.com/docker/docker/api/types/strslice"
3127
"github.com/nitrictech/newcli/pkg/build"
32-
"github.com/nitrictech/newcli/pkg/containerengine"
3328
"github.com/nitrictech/newcli/pkg/provider/run"
3429
"github.com/nitrictech/nitric/pkg/membrane"
3530
boltdb_service "github.com/nitrictech/nitric/pkg/plugins/document/boltdb"
@@ -56,8 +51,6 @@ var runCmd = &cobra.Command{
5651
cobra.CheckErr(err)
5752
}
5853

59-
ce, err := containerengine.Discover()
60-
6154
// Prepare development images
6255
ctx, _ := filepath.Abs(".")
6356
if err := build.CreateBaseDev(ctx, map[string]string{
@@ -134,41 +127,13 @@ var runCmd = &cobra.Command{
134127

135128
time.Sleep(time.Second * time.Duration(2))
136129

137-
// Start the functions
138-
// cids := make([]string, 0)
139-
fmt.Println("found files:", files)
140-
for i, f := range files {
141-
hostConfig := &container.HostConfig{
142-
AutoRemove: true,
143-
Mounts: []mount.Mount{
144-
{
145-
Type: "bind",
146-
Source: ctx,
147-
Target: "/app",
148-
},
149-
},
150-
}
151-
if runtime.GOOS == "linux" {
152-
// setup host.docker.internal to route to host gateway
153-
// to access rpc server hosted by local CLI run
154-
hostConfig.ExtraHosts = []string{"host.docker.internal:172.17.0.1"}
155-
}
156-
157-
cID, err := ce.ContainerCreate(&container.Config{
158-
Image: "nitric-ts-dev", // Select an image to use based on the handler
159-
// Set the address to the bound port
160-
Env: []string{fmt.Sprintf("SERVICE_ADDRESS=host.docker.internal:%d", 50051)},
161-
Entrypoint: strslice.StrSlice{"nodemon"},
162-
Cmd: strslice.StrSlice{"--watch", "/app/**", "--ext", "ts,json", "--exec", "ts-node -T " + "/app/" + f},
163-
}, hostConfig, nil, fmt.Sprintf("test-container-%d", i))
164-
165-
if err != nil {
166-
cobra.CheckErr(err)
167-
}
168-
169-
// cids = append(cids, cID)
170-
171-
err = ce.Start(cID)
130+
functions, err := run.FunctionsFromHandlers(".", files)
131+
if err != nil {
132+
cobra.CheckErr(err)
133+
}
134+
135+
for _, f := range functions {
136+
err = f.Start()
172137
}
173138

174139
fmt.Println("Local running, use ctrl-C to stop")

pkg/provider/run/function.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package run
2+
3+
import (
4+
"fmt"
5+
"path/filepath"
6+
"runtime"
7+
"strings"
8+
9+
"github.com/docker/docker/api/types/container"
10+
"github.com/docker/docker/api/types/mount"
11+
"github.com/nitrictech/newcli/pkg/containerengine"
12+
)
13+
14+
type Function struct {
15+
handler string
16+
runCtx string
17+
runtime Runtime
18+
ce containerengine.ContainerEngine
19+
// Container id populated after a call to Start
20+
cid string
21+
}
22+
23+
func (f *Function) Name() string {
24+
return strings.Replace(filepath.Base(f.handler), filepath.Ext(f.handler), "", 1)
25+
}
26+
27+
func (f *Function) Start() error {
28+
hostConfig := &container.HostConfig{
29+
AutoRemove: true,
30+
Mounts: []mount.Mount{
31+
{
32+
Type: "bind",
33+
Source: f.runCtx,
34+
Target: "/app",
35+
},
36+
},
37+
}
38+
if runtime.GOOS == "linux" {
39+
// setup host.docker.internal to route to host gateway
40+
// to access rpc server hosted by local CLI run
41+
hostConfig.ExtraHosts = []string{"host.docker.internal:172.17.0.1"}
42+
}
43+
44+
launchOpts, err := launchOptsForFunction(f)
45+
if err != nil {
46+
return err
47+
}
48+
49+
cID, err := f.ce.ContainerCreate(&container.Config{
50+
Image: devImageNameForRuntime(f.runtime), // Select an image to use based on the handler
51+
// Set the address to the bound port
52+
Env: []string{fmt.Sprintf("SERVICE_ADDRESS=host.docker.internal:%d", 50051)},
53+
Entrypoint: launchOpts.Entrypoint,
54+
Cmd: launchOpts.Cmd,
55+
}, hostConfig, nil, f.Name())
56+
57+
if err != nil {
58+
return err
59+
}
60+
61+
f.cid = cID
62+
63+
return f.ce.Start(cID)
64+
}
65+
66+
func (f *Function) Stop() error {
67+
return f.ce.Stop(f.cid, nil)
68+
}
69+
70+
type FunctionOpts struct {
71+
Handler string
72+
RunCtx string
73+
ContainerEngine containerengine.ContainerEngine
74+
}
75+
76+
func NewFunction(opts FunctionOpts) (*Function, error) {
77+
78+
var runtime Runtime = RuntimeTypescript
79+
80+
switch Runtime(filepath.Ext(opts.Handler)) {
81+
case RuntimeTypescript:
82+
runtime = RuntimeTypescript
83+
case RuntimeJavascript:
84+
runtime = RuntimeJavascript
85+
default:
86+
return nil, fmt.Errorf("no runtime supported for handler: %s", opts.Handler)
87+
}
88+
89+
return &Function{
90+
runtime: runtime,
91+
handler: opts.Handler,
92+
runCtx: opts.RunCtx,
93+
}, nil
94+
}
95+
96+
func FunctionsFromHandlers(runCtx string, handlers []string) ([]*Function, error) {
97+
funcs := make([]*Function, 0, len(handlers))
98+
ce, err := containerengine.Discover()
99+
100+
if err != nil {
101+
return nil, err
102+
}
103+
104+
for _, h := range handlers {
105+
if f, err := NewFunction(FunctionOpts{
106+
RunCtx: runCtx,
107+
Handler: h,
108+
ContainerEngine: ce,
109+
}); err != nil {
110+
return nil, err
111+
} else {
112+
funcs = append(funcs, f)
113+
}
114+
}
115+
116+
return funcs, nil
117+
}

pkg/provider/run/runtime.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package run
2+
3+
import (
4+
"fmt"
5+
"path/filepath"
6+
7+
"github.com/docker/docker/api/types/strslice"
8+
"github.com/nitrictech/newcli/pkg/build"
9+
"github.com/spf13/cobra"
10+
)
11+
12+
type Runtime string
13+
14+
const (
15+
RuntimeTypescript Runtime = "ts"
16+
RuntimeJavascript Runtime = "js"
17+
)
18+
19+
func devImageNameForRuntime(runtime Runtime) string {
20+
return fmt.Sprintf("nitric-%s-dev", runtime)
21+
}
22+
23+
type LaunchOpts struct {
24+
Entrypoint []string
25+
Cmd []string
26+
}
27+
28+
func launchOptsForFunction(f *Function) (LaunchOpts, error) {
29+
switch f.runtime {
30+
// Javascript will re-use typescript runtime
31+
case RuntimeJavascript:
32+
case RuntimeTypescript:
33+
return LaunchOpts{
34+
Entrypoint: strslice.StrSlice{"nodemon"},
35+
Cmd: strslice.StrSlice{"--watch", "/app/**", "--ext", "ts,js,json", "--exec", "ts-node -T " + "/app/" + f.handler},
36+
}, nil
37+
}
38+
39+
return LaunchOpts{}, fmt.Errorf("unsupported runtime")
40+
}
41+
42+
func CreateBaseDevForFunctions(funcs []*Function) error {
43+
ctx, _ := filepath.Abs(".")
44+
if err := build.CreateBaseDev(ctx, map[string]string{
45+
"ts": "nitric-ts-dev",
46+
}); err != nil {
47+
cobra.CheckErr(err)
48+
}
49+
50+
imageBuilds := make(map[string]string)
51+
52+
for _, f := range funcs {
53+
switch f.runtime {
54+
// Javascript will re-use typescript runtime
55+
case RuntimeJavascript:
56+
case RuntimeTypescript:
57+
imageBuilds[string(RuntimeTypescript)] = devImageNameForRuntime(RuntimeTypescript)
58+
}
59+
}
60+
61+
// Currently the file context does not matter (base runtime images should not copy files)
62+
return build.CreateBaseDev(".", imageBuilds)
63+
}

0 commit comments

Comments
 (0)