Skip to content

Commit beab41c

Browse files
committed
Cleaned up repo + added README
1 parent 55f9645 commit beab41c

8 files changed

Lines changed: 90 additions & 48 deletions

File tree

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ COPY . .
66
# Future: Speed up builds by also copying the mod cache ($GOPATH/pkg/mod)
77

88
ENV GO111MODULE=on
9-
RUN go get
109
WORKDIR /go/src/github.com/erwinvaneyk/simfaas/cmd/simfission
10+
RUN go get
1111
RUN CGO_ENABLED=0 go build \
1212
-gcflags=-trimpath="/go/src/github.com/erwinvaneyk/simfaas" \
1313
-asmflags=-trimpath="/go/src/github.com/erwinvaneyk/simfaas" \

Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
REPO=docker.io/erwinvaneyk
22
IMAGE=simfission
33
VERSION=latest
4-
ROOT_DIR=$(dirname $0)
54

65
.PHONY: publish test build install
76

README.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,21 @@
1-
# simfaas
1+
# SimFaaS
2+
3+
SimFaaS is aimed to be a generic FaaS emulator/simulator (though currently it
4+
is just an emulator). The goal is to be able to evaluate key metrics, such as
5+
runtime, cold start duration and resource cost, in FaaS platforms.
6+
7+
## Building
8+
9+
See Makefile.
10+
11+
## Fission
12+
13+
SimFaaS includes a specific implementation for Fission called: **SimFission**.
14+
SimFission is a wrapper on top of simfaas that emulates a part of the
15+
API of Fission.
16+
17+
It currently emulates the following part of the (web) API:
18+
1. Resolving a function name to a service.
19+
2. Tapping of a service.
20+
3. Executing a fission function.
21+
4. Getting info for a given function.

cmd/simfission/simfission.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@ import (
1212
"time"
1313
)
1414

15-
// simfaas - is a very simple mock of a FaaS platform to implement the sleep function with minimal interference
16-
1715
var (
16+
// buildTime is a UNIX datetime that should be injected at build time.
1817
buildTime string // UNIX
1918

2019
//
@@ -82,7 +81,7 @@ func main() {
8281
// Parse arguments
8382
coldStart := flag.Duration("cold-start", 0, "The default cold start duration")
8483
keepWarm := flag.Duration("keep-warm", 0, "How long the function should be kept warm after an execution.")
85-
addr := flag.String("addr", ":8888", "Address to bind the server to.")
84+
addr := flag.String("addr", ":8888", "Address serve the API on.")
8685
flag.Parse()
8786
log.Printf("simfission %s", buildTime)
8887

@@ -108,6 +107,7 @@ func main() {
108107
if err := fission.Start(); err != nil {
109108
log.Fatalf("Failed to start FaaS simulator: %v", err)
110109
}
110+
defer fission.Close()
111111

112112
// Publish FaaS simulator resource usage to Prometheus
113113
go func() {

fission.go

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,28 @@ import (
1313
`time`
1414
)
1515

16+
// Fission is a wrapper on top of simfaas that emulates a part of the
17+
// interface of Fission.
1618
type Fission struct {
1719
Platform *Platform
1820
FnFactory func(name string) *FunctionConfig
21+
22+
// CreateUndefinedFunctions enables, if set to true,
23+
// the automatic creation of a function if it is called.
1924
CreateUndefinedFunctions bool
2025
}
2126

27+
func (f *Fission) Start() error {
28+
return f.Platform.Start()
29+
}
30+
31+
func (f *Fission) Close() error {
32+
return f.Platform.Close()
33+
}
34+
35+
// GetServiceForFunction emulates the mapping of a function to a service
36+
// name/host. Currently it just returns the name of the function as the
37+
// service name.
2238
func (f *Fission) GetServiceForFunction(fnName string) (string, error) {
2339
f.createIfUndefined(fnName)
2440
fn, ok := f.Platform.Get(fnName)
@@ -28,7 +44,10 @@ func (f *Fission) GetServiceForFunction(fnName string) (string, error) {
2844
return fn.name, nil
2945
}
3046

31-
// We assume that url is just the function name
47+
// TapService deploys (or keeps deployed) a function instance for the function.
48+
//
49+
// Note: similar as in GetServiceForFunction, we assume that the service url is
50+
// just the function name.
3251
func (f *Fission) TapService(svcURL string) error {
3352
if len(svcURL) == 0 {
3453
return errors.New("no url provided to tap")
@@ -48,6 +67,15 @@ func (f *Fission) TapService(svcURL string) error {
4867
return nil
4968
}
5069

70+
// Run emulates the execution of a Fission Function.
71+
//
72+
// If the runtime is not nil it will be used to override the runtime
73+
// specified in the config of the function.
74+
func (f *Fission) Run(fnName string, runtime *time.Duration) (*ExecutionReport, error) {
75+
f.createIfUndefined(fnName)
76+
return f.Platform.Run(fnName, runtime)
77+
}
78+
5179
func (f *Fission) Serve() http.Handler {
5280
handler := &RegexpHandler{}
5381
handler.HandleFunc(regexp.MustCompile("/v2/functions/.*"), f.HandleFunctionsGet)
@@ -57,7 +85,8 @@ func (f *Fission) Serve() http.Handler {
5785
return handler
5886
}
5987

60-
// /v2/getServiceForFunction
88+
// HandleGetServiceForFunction emulates the /v2/getServiceForFunction
89+
// Fission endpoint.
6190
func (f *Fission) HandleGetServiceForFunction(w http.ResponseWriter, r *http.Request) {
6291
bs, err := ioutil.ReadAll(r.Body)
6392
r.Body.Close()
@@ -81,11 +110,7 @@ func (f *Fission) HandleGetServiceForFunction(w http.ResponseWriter, r *http.Req
81110
w.Write([]byte(svc))
82111
}
83112

84-
func (f *Fission) Start() error {
85-
return f.Platform.Start()
86-
}
87-
88-
// /v2/tapService
113+
// HandleTapService emulates the /v2/tapService Fission endpoint.
89114
func (f *Fission) HandleTapService(w http.ResponseWriter, r *http.Request) {
90115
bs, err := ioutil.ReadAll(r.Body)
91116
defer r.Body.Close()
@@ -105,19 +130,22 @@ func (f *Fission) HandleTapService(w http.ResponseWriter, r *http.Request) {
105130
w.WriteHeader(http.StatusOK)
106131
}
107132

108-
// /v2/functions/.*
133+
// HandleFunctionsGet emulates the /v2/functions/.* Fission endpoints.
134+
// Currently it simply returns an empty map.
109135
func (f *Fission) HandleFunctionsGet(w http.ResponseWriter, r *http.Request) {
110136
w.WriteHeader(http.StatusOK)
111137
w.Write([]byte("{}"))
112138
}
113139

114-
// /fission-function/
140+
// HandleFunctionRun emulates the /fission-function/.* Fission endpoints.
141+
//
142+
// It checks for the presence of the runtime query parameter,
143+
// which allows you to override the runtime of the function.
115144
func (f *Fission) HandleFunctionRun(w http.ResponseWriter, r *http.Request) {
116145
// Parse arguments: fnname, runtime
117146
var seconds float64
118147
var err error
119148
if queryRuntime := r.URL.Query().Get("runtime"); len(queryRuntime) > 0 {
120-
// Read query
121149
seconds, err = strconv.ParseFloat(queryRuntime, 64)
122150
if err != nil {
123151
http.Error(w, err.Error(), http.StatusBadRequest)
@@ -126,22 +154,18 @@ func (f *Fission) HandleFunctionRun(w http.ResponseWriter, r *http.Request) {
126154
}
127155
runtime := time.Duration(seconds * float64(time.Second))
128156
fnName := getFunctionNameFromUrl(r.URL)
129-
f.createIfUndefined(fnName)
130157

131-
// Run function
132-
report, err := f.Platform.Run(fnName, &runtime)
158+
report, err := f.Run(fnName, &runtime)
133159
if err != nil {
134160
http.Error(w, err.Error(), http.StatusBadRequest)
135161
return
136162
}
137163

138-
// Simulate runtime
139-
result, _ := json.Marshal(map[string]interface{}{
140-
"started_at": report.StartedAt.UnixNano(),
141-
"finished_at": report.FinishedAt.UnixNano(),
142-
"coldStart": report.ColdStart.Nanoseconds(),
143-
"runtime": report.Runtime.Nanoseconds(),
144-
})
164+
result, err := json.Marshal(report)
165+
if err != nil {
166+
http.Error(w, err.Error(), http.StatusInternalServerError)
167+
return
168+
}
145169
w.WriteHeader(http.StatusOK)
146170
w.Write(result)
147171
}
@@ -162,8 +186,6 @@ type ObjectMeta struct {
162186
// Namespace string `json:"namespace,omitempty" protobuf:"bytes,3,opt,name=namespace"`
163187
}
164188

165-
var fnUrlRegEx = regexp.MustCompile("/(.*)$")
166-
167189
func getFunctionNameFromUrl(url *url.URL) string {
168190
return url.Path[strings.LastIndex(url.Path, "/")+1:]
169191
}

fission_test.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import (
55
`testing`
66
)
77

8-
func TestFission_Run(t *testing.T) {
9-
simFission := NewFission(0, 0)
8+
func TestFission_Setup(t *testing.T) {
9+
simFission := Fission{
10+
Platform: New(),
11+
}
1012
srv := httptest.NewServer(simFission.Serve())
11-
defer srv.Close()
13+
srv.Close()
1214
}

httputil.go

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,8 @@ import (
55
`regexp`
66
)
77

8-
//
9-
// To enable wildcards
10-
//
11-
12-
type route struct {
13-
pattern *regexp.Regexp
14-
handler http.Handler
15-
}
16-
8+
// RegexpHandler is simple http.Handler to enable the use of
9+
// wildcards in routes.
1710
type RegexpHandler struct {
1811
routes []*route
1912
}
@@ -38,3 +31,8 @@ func (h *RegexpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
3831
// no pattern matched; send 404 response
3932
http.NotFound(w, r)
4033
}
34+
35+
type route struct {
36+
pattern *regexp.Regexp
37+
handler http.Handler
38+
}

simfaas.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ type FunctionConfig struct {
2828
}
2929

3030
type ExecutionReport struct {
31-
ColdStart time.Duration
32-
Runtime time.Duration
33-
StartedAt time.Time
34-
FinishedAt time.Time
31+
ColdStart time.Duration `json:"cold_start"`
32+
Runtime time.Duration `json:"runtime"`
33+
StartedAt time.Time `json:"started_at"`
34+
FinishedAt time.Time `json:"finished_at"`
3535
}
3636

3737
type Function struct {
@@ -47,8 +47,8 @@ type Function struct {
4747
// active reports the number of executions of this function currently running.
4848
active atomic.Uint32
4949

50-
// queued reports the number of executions of this function currently queued, waiting for instances to free up or
51-
// additional to be deployed.
50+
// queued reports the number of executions of this function currently queued,
51+
// waiting for instances to free up or additional to be deployed.
5252
queued atomic.Uint32
5353
}
5454

@@ -136,9 +136,10 @@ func (p *Platform) cleanup(fn *Function) {
136136
fn.instances.Store(0)
137137
}
138138

139-
// Run emulates a function execution in a synchronous way, sleeping for the entire executionRuntime
139+
// Run emulates a function execution in a synchronous way,
140+
// sleeping for the entire executionRuntime.
140141
//
141-
// TODO handle inputs and outputs
142+
// TODO emulate inputs and outputs
142143
func (p *Platform) Run(fnName string, executionRuntime *time.Duration) (*ExecutionReport, error) {
143144
startedAt := time.Now()
144145
// Find the function

0 commit comments

Comments
 (0)