Skip to content

Commit 3e2893d

Browse files
author
CI
committed
Releasing version 0.3.770
1 parent 9f6d06f commit 3e2893d

41 files changed

Lines changed: 691 additions & 227 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,5 @@ fnlb/fnlb
3232
/fnserver
3333
*iml
3434
target/
35+
clients/.bundle
36+
clients/vendor

Dockerfile

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,24 @@
1-
FROM docker-remote.artifactory.oci.oraclecorp.com/docker:28-dind
1+
ARG BUILDER="builder-buildservice"
2+
# The builder-local is only used for local development where we could build the fnserver
3+
# in local linux container
4+
FROM ocr-docker-remote.artifactory.oci.oraclecorp.com/os/oraclelinux:8 AS builder-local
5+
RUN dnf -y install golang git ca-certificates && dnf clean all
6+
7+
WORKDIR /home/fnserver
8+
9+
COPY . .
10+
11+
RUN CGO_ENABLED=0 go build -o fnserver ./cmd/fnserver/main.go
12+
13+
# For build in buildserver, the artifact is copied from previous go build step.
14+
FROM scratch AS builder-buildservice
15+
16+
WORKDIR /home/fnserver
17+
COPY fnserver .
18+
19+
FROM ${BUILDER} AS fnserver-binary
20+
21+
FROM docker-remote.artifactory.oci.oraclecorp.com/docker:29-dind
222

323
RUN apk add --no-cache ca-certificates
424

@@ -8,7 +28,7 @@ ENTRYPOINT ["preentry.sh"]
828

929
WORKDIR /app
1030

11-
COPY fnserver .
31+
COPY --from=fnserver-binary /home/fnserver/fnserver .
1232

1333
CMD ["./fnserver"]
1434
EXPOSE 8080

Makefile

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,21 @@ test-build-arm:
103103

104104
.PHONY: run
105105
run: build
106-
GIN_MODE=debug ./fnserver
106+
FN_HOT_START_TIMEOUT_MSECS=300000 FN_LOG_LEVEL=debug GIN_MODE=debug ./fnserver
107107

108108
.PHONY: docker-build
109109
docker-build:
110-
docker build --build-arg HTTPS_PROXY --build-arg HTTP_PROXY -t fnproject/fnserver:latest .
110+
docker build --build-arg HTTPS_PROXY --build-arg HTTP_PROXY --build-arg BUILDER=builder-local -t fnproject/fnserver:latest .
111111

112112
.PHONY: docker-run
113113
docker-run: docker-build
114-
docker run --rm --privileged -it -e NO_PROXY -e HTTP_PROXY -e FN_LOG_LEVEL=debug -e "FN_DB_URL=sqlite3:///app/data/fn.db" -v ${CURDIR}/data:/app/data -p 8080:8080 fnproject/fnserver
114+
docker run --rm --privileged -i --name fnserver -e FN_LOG_LEVEL=debug \
115+
-v ${CURDIR}/data:/app/data -p 8080:8080 \
116+
-v fniofsvol:/iofs:z -e FN_IOFS_DOCKER_PATH=fniofsvol -e FN_IOFS_PATH=/iofs \
117+
-v /var/run/docker.sock:/var/run/docker.sock -e FN_HOT_START_TIMEOUT_MSECS=300000 \
118+
-e FN_LOCAL_DEBUG=true -e FN_LOCAL_DEBUG_PORT=5678 \
119+
--entrypoint ./fnserver \
120+
fnproject/fnserver:latest
115121

116122
.PHONY: docker-test
117123
docker-test:

api/agent/agent.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ import (
3333
)
3434

3535
const (
36-
pauseTimeout = 5 * time.Second // docker pause/unpause
36+
pauseTimeout = 5 * time.Second // docker pause/unpause
37+
defaultDebugTimeout = 300 // minimum 5 mins timeout if debug mode is on.
38+
// user could override it in func.yaml if they want larger value.
3739
)
3840

3941
// Agent exposes an api to create calls from various parameters and then submit
@@ -145,6 +147,13 @@ func New(options ...Option) Agent {
145147

146148
a.resources = NewResourceTracker(&a.cfg)
147149

150+
if a.cfg.LocalDebug {
151+
WithCallOptions(func(c *call) error {
152+
c.Timeout = max(defaultDebugTimeout, c.Timeout)
153+
return nil
154+
})
155+
}
156+
148157
for _, sup := range a.onStartup {
149158
sup()
150159
}
@@ -1170,6 +1179,7 @@ type container struct {
11701179
afterCall drivers.AfterCall
11711180
dockerAuth dockerdriver.Auther
11721181
authToken string
1182+
exposedPort *uint64
11731183

11741184
stderr io.Writer
11751185

@@ -1258,6 +1268,11 @@ func newHotContainer(ctx context.Context, evictor Evictor, caller *slotCaller, c
12581268
logger.WithField("FN_LISTENER", env["FN_LISTENER"]).
12591269
Debug("Setting FN_LISTENER in container")
12601270

1271+
var localDebugPort *uint64 = nil
1272+
if cfg.LocalDebug {
1273+
localDebugPort = &cfg.LocalDebugPort
1274+
}
1275+
12611276
return &container{
12621277
id: id, // XXX we could just let docker generate ids...
12631278
image: call.Image,
@@ -1273,6 +1288,7 @@ func newHotContainer(ctx context.Context, evictor Evictor, caller *slotCaller, c
12731288
messageQueue: cfg.MaxMessageQueue,
12741289
tmpFsSize: uint64(call.TmpFsSize),
12751290
disableNet: call.disableNet,
1291+
exposedPort: localDebugPort,
12761292
iofs: iofs,
12771293
dockerAuth: call.dockerAuth,
12781294
authToken: authToken,
@@ -1366,6 +1382,7 @@ func (c *container) UDSAgentPath() string { return c.iofs.AgentPat
13661382
func (c *container) UDSDockerPath() string { return c.iofs.DockerPath() }
13671383
func (c *container) UDSDockerDest() string { return iofsDockerMountDest }
13681384
func (c *container) DisableNet() bool { return c.disableNet }
1385+
func (c *container) ExposedPort() *uint64 { return c.exposedPort }
13691386

13701387
// WriteStat publishes each metric in the specified Stats structure as a histogram metric
13711388
func (c *container) WriteStat(ctx context.Context, stat driver_stats.Stat) {

api/agent/config.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ type Config struct {
4949
ImageCleanMaxSize uint64 `json:"image_clean_max_size"`
5050
ImageCleanExemptTags string `json:"image_clean_exempt_tags"`
5151
ImageEnableVolume bool `json:"image_enable_volume"`
52+
LocalDebug bool `json:"local_debug"`
53+
LocalDebugPort uint64 `json:"local_debug_port"`
5254
}
5355

5456
const (
@@ -134,6 +136,11 @@ const (
134136
// EnvDetachedHeadroom is the extra room we want to give to a detached function to run.
135137
EnvDetachedHeadroom = "FN_EXECUTION_HEADROOM"
136138

139+
// EnvLocalDebug is the flag to control if Fn Container will be started with FN_LOCAL_DEBUG_PORT exposed
140+
// for debugger attachment
141+
EnvLocalDebug = "FN_LOCAL_DEBUG"
142+
EnvLocalDebugPort = "FN_LOCAL_DEBUG_PORT"
143+
137144
// MaxMsDisabled is used to determine whether mr freeze is lying in wait. TODO remove this manuever
138145
MaxMsDisabled = time.Duration(math.MaxInt64)
139146

@@ -164,6 +171,7 @@ func NewConfig() (*Config, error) {
164171
defaultMaxLockedMemory := uint64(64 * 1024)
165172
defaultMaxPendingSignals := uint64(5000)
166173
defaultMaxMessageQueue := uint64(819200)
174+
defaultLocalDebugPort := uint64(5678)
167175

168176
var err error
169177
err = setEnvMsecs(err, EnvFreezeIdle, &cfg.FreezeIdle, 50*time.Millisecond)
@@ -203,6 +211,8 @@ func NewConfig() (*Config, error) {
203211
err = setEnvUint(err, EnvImageCleanMaxSize, &cfg.ImageCleanMaxSize, nil)
204212
err = setEnvStr(err, EnvImageCleanExemptTags, &cfg.ImageCleanExemptTags)
205213
err = setEnvBool(err, EnvImageEnableVolume, &cfg.ImageEnableVolume)
214+
err = setEnvBool(err, EnvLocalDebug, &cfg.LocalDebug)
215+
err = setEnvUint(err, EnvLocalDebugPort, &cfg.LocalDebugPort, &defaultLocalDebugPort)
206216

207217
if err != nil {
208218
return cfg, err

api/agent/drivers/docker/cookie.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,23 @@ func (c *cookie) configureWorkDir(log logrus.FieldLogger) {
262262
c.opts.Config.WorkingDir = wd
263263
}
264264

265+
func (c *cookie) configureLocalDebugPortMapping(log logrus.FieldLogger) {
266+
if c.task.ExposedPort() != nil {
267+
log.WithFields(logrus.Fields{"call_id": c.task.Id()}).Debug("configure local debug port mapping")
268+
var port = fmt.Sprintf("%d/tcp", *c.task.ExposedPort())
269+
c.opts.Config.ExposedPorts = map[docker.Port]struct{}{
270+
docker.Port(port): {},
271+
}
272+
c.opts.HostConfig.PortBindings = map[docker.Port][]docker.PortBinding{
273+
docker.Port(port): {{
274+
HostIP: "0.0.0.0",
275+
HostPort: fmt.Sprintf("%d", *c.task.ExposedPort()),
276+
}},
277+
}
278+
}
279+
280+
}
281+
265282
func (c *cookie) configureNetwork(log logrus.FieldLogger) {
266283
if c.opts.HostConfig.NetworkMode != "" {
267284
return

api/agent/drivers/docker/docker.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ func (drv *DockerDriver) CreateCookie(ctx context.Context, task drivers.Containe
375375
cookie.configurePIDs(log)
376376
cookie.configureULimits(log)
377377
cookie.configureTmpFs(log)
378+
cookie.configureLocalDebugPortMapping(log)
378379
cookie.configureVolumes(log)
379380
cookie.configureWorkDir(log)
380381
cookie.configureIOFS(log)

api/agent/drivers/docker/docker_test.go

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@ import (
1919
)
2020

2121
type taskDockerTest struct {
22-
id string
23-
cmd string
24-
disableNet bool
25-
input io.Reader
26-
output io.Writer
27-
errors io.Writer
28-
logURL string
22+
id string
23+
cmd string
24+
disableNet bool
25+
input io.Reader
26+
output io.Writer
27+
errors io.Writer
28+
logURL string
29+
exposedPort *uint64
2930
}
3031

3132
func (f *taskDockerTest) Command() string { return f.cmd }
@@ -67,6 +68,7 @@ func (f *taskDockerTest) BeforeCall(context.Context, *models.Call, drivers.CallE
6768
func (f *taskDockerTest) AfterCall(context.Context, *models.Call, drivers.CallExtensions) error {
6869
return nil
6970
}
71+
func (f *taskDockerTest) ExposedPort() *uint64 { return f.exposedPort }
7072

7173
func createTask(id string) *taskDockerTest {
7274
return &taskDockerTest{
@@ -557,3 +559,59 @@ func TestRunnerDockerInvalidSyslog(t *testing.T) {
557559
}
558560

559561
}
562+
563+
func TestRunnerDockerLocalDebug(t *testing.T) {
564+
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(30)*time.Second)
565+
defer cancel()
566+
567+
dkr := NewDocker(drivers.Config{})
568+
defer dkr.Close()
569+
570+
var output bytes.Buffer
571+
var errors bytes.Buffer
572+
var exposedPort uint64 = 5678
573+
574+
task := createTask("test-docker-local-debug")
575+
task.output = &output
576+
task.errors = &errors
577+
task.exposedPort = &exposedPort
578+
579+
cookie, err := dkr.CreateCookie(ctx, task)
580+
if err != nil {
581+
t.Fatal("Couldn't create task cookie")
582+
}
583+
584+
defer cookie.Close(ctx)
585+
586+
err = commonCookiePull(ctx, cookie)
587+
if err != nil {
588+
t.Fatal(err)
589+
}
590+
err, result := commonCookieRun(ctx, cookie)
591+
if err != nil {
592+
t.Fatal(err)
593+
}
594+
if result.Error() != nil {
595+
t.Fatal(result.Error())
596+
}
597+
598+
if result.Status() != "success" {
599+
t.Fatalf("Test should successfully run the image: %s output: %s errors: %s",
600+
result.Error(), output.String(), errors.String())
601+
}
602+
603+
port := docker.Port("5678/tcp")
604+
var containerOptions docker.CreateContainerOptions
605+
containerOptions = cookie.ContainerOptions().(docker.CreateContainerOptions)
606+
if _, ok := containerOptions.Config.ExposedPorts[port]; !ok {
607+
t.Errorf("Expected ExposedPorts to contain 5678/tcp, got: %+v", containerOptions.Config.ExposedPorts)
608+
}
609+
bindings, ok := containerOptions.HostConfig.PortBindings[port]
610+
if !ok || len(bindings) != 1 {
611+
t.Fatalf("Expected PortBindings for '5678/tcp', got: %+v", containerOptions.HostConfig.PortBindings)
612+
}
613+
binding := bindings[0]
614+
if binding.HostIP != "0.0.0.0" || binding.HostPort != "5678" {
615+
t.Errorf("Expected HostIP '0.0.0.0' and HostPort '5678', got HostIP '%s', HostPort '%s'", binding.HostIP, binding.HostPort)
616+
}
617+
}

api/agent/drivers/driver.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,9 @@ type ContainerTask interface {
209209
// Returns true if network is disabled.
210210
DisableNet() bool
211211

212+
// Port exposed in Fn Container for local debugger to attach to
213+
ExposedPort() *uint64
214+
212215
// BeforeCall is invoked just prior to running an invocation.
213216
// The Task is definitely going to be used for this invocation.
214217
// Invocation extensions are passed to the Before and After calls

api/version/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
package version
22

33
// Version of Functions
4-
var Version = "0.3.769"
4+
var Version = "0.3.770"

0 commit comments

Comments
 (0)