Skip to content

Commit afaedb0

Browse files
authored
feat: use temp directory for client server logs (#85)
Testing the client locally typically means testing from the root of an FF repo, so this prevents the FF repo from needing to .gitignore the server logs files that are produced by the client. Also, eliminate the cross-binary dependency of the GitHub Action and the conformance test client on knowing the logs file name by having the client itself print the server logs on error.
1 parent 59d70bd commit afaedb0

File tree

9 files changed

+71
-66
lines changed

9 files changed

+71
-66
lines changed

action/dist/index.js

Lines changed: 1 addition & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

action/dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

action/src/index.ts

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,6 @@ import * as childProcess from 'child_process';
33
import * as fs from 'fs';
44
import * as process from 'process';
55

6-
/**
7-
* writeFileToConsole contents of file to console.
8-
* @param {string} path - filepath to write to the console
9-
*/
10-
function writeFileToConsole(path: string) {
11-
try {
12-
const data = fs.readFileSync(path, 'utf8');
13-
console.log(`${path}: ${data}`);
14-
} catch (e) {
15-
console.log(`$unable to read {path}, skipping: ${e}`);
16-
}
17-
}
18-
196
/**
207
* Run a specified command.
218
* @param {string} cmd - command to run
@@ -25,9 +12,6 @@ function runCmd(cmd: string) {
2512
console.log(`RUNNING: "${cmd}"`)
2613
childProcess.execSync(cmd);
2714
} catch (error) {
28-
writeFileToConsole('serverlog_stdout.txt');
29-
writeFileToConsole('serverlog_stderr.txt');
30-
writeFileToConsole('function_output.json');
3115
core.setFailed(error.message);
3216
}
3317
}
@@ -58,7 +42,7 @@ async function run() {
5842
runCmd(`git fetch origin refs/tags/${version} && git checkout ${version}`);
5943
} else {
6044
// Checkout latest release tag.
61-
runCmd(`git fetch --tags && git checkout $(git describe --tags 'git rev-list --tags --max-count=1')`)
45+
runCmd('git fetch --tags && git checkout $(git describe --tags $(git rev-list --tags --max-count=1))')
6246
}
6347
runCmd(`go build -o ~/client`);
6448

client/buildpacks.go

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,22 @@ const (
3333
)
3434

3535
type buildpacksFunctionServer struct {
36-
output string
37-
source string
38-
target string
39-
funcType string
40-
runtime string
41-
tag string
42-
ctID string
43-
logStdout *os.File
44-
logStderr *os.File
36+
output string
37+
source string
38+
target string
39+
funcType string
40+
runtime string
41+
tag string
42+
ctID string
43+
logStdout *os.File
44+
logStderr *os.File
45+
stdoutFile string
46+
stderrFile string
4547
}
4648

47-
func (b *buildpacksFunctionServer) Start() (func(), error) {
49+
func (b *buildpacksFunctionServer) Start(stdoutFile, stderrFile string) (func(), error) {
50+
b.stdoutFile = stdoutFile
51+
b.stderrFile = stderrFile
4852
typ := *functionType
4953
if typ == "legacyevent" {
5054
typ = "event"
@@ -105,12 +109,12 @@ func (b *buildpacksFunctionServer) build(ctx context.Context) error {
105109
func (b *buildpacksFunctionServer) run() (func(), error) {
106110
// Create logs output files.
107111
var err error
108-
b.logStdout, err = os.Create(stdoutFile)
112+
b.logStdout, err = os.Create(b.stdoutFile)
109113
if err != nil {
110114
return nil, err
111115
}
112116

113-
b.logStderr, err = os.Create(stderrFile)
117+
b.logStderr, err = os.Create(b.stderrFile)
114118
if err != nil {
115119
return nil, err
116120
}
@@ -146,7 +150,7 @@ func (b *buildpacksFunctionServer) run() (func(), error) {
146150
if err := b.killContainer(); err != nil {
147151
log.Fatalf("failed to kill container: %v", err)
148152
}
149-
log.Printf("Framework server shut down. Wrote logs to %v and %v.", stdoutFile, stderrFile)
153+
log.Printf("Framework server shut down. Wrote logs to %v and %v.", b.stdoutFile, b.stderrFile)
150154
}, nil
151155
}
152156

client/local.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,25 @@ import (
2323
)
2424

2525
type localFunctionServer struct {
26-
output string
27-
cmd string
26+
output string
27+
cmd string
28+
stdoutFile string
29+
stderrFile string
2830
}
2931

30-
func (l *localFunctionServer) Start() (func(), error) {
32+
func (l *localFunctionServer) Start(stdoutFile, stderrFile string) (func(), error) {
33+
l.stdoutFile = stdoutFile
34+
l.stderrFile = stderrFile
3135
args := strings.Fields(l.cmd)
3236
cmd := newCmd(args)
3337

34-
stdout, err := os.Create(stdoutFile)
38+
stdout, err := os.Create(l.stdoutFile)
3539
if err != nil {
3640
return nil, err
3741
}
3842
cmd.Stdout = stdout
3943

40-
stderr, err := os.Create(stderrFile)
44+
stderr, err := os.Create(l.stderrFile)
4145
if err != nil {
4246
return nil, err
4347
}
@@ -59,7 +63,7 @@ func (l *localFunctionServer) Start() (func(), error) {
5963
log.Fatalf("Failed to shut down framework server: %v", err)
6064
}
6165

62-
log.Printf("Framework server shut down. Wrote logs to %v and %v.", stdoutFile, stderrFile)
66+
log.Printf("Framework server shut down. Wrote logs to %v and %v.", l.stdoutFile, l.stderrFile)
6367
}
6468
return shutdown, nil
6569
}

client/local_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func TestStartAndShutdown(t *testing.T) {
4949
cmd: fmt.Sprintf("go run %s", f),
5050
}
5151

52-
shutdown, err := server.Start()
52+
shutdown, err := server.Start(defaultStdoutFile, defaultStderrFile)
5353
if shutdown != nil {
5454
defer shutdown()
5555
}

client/main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,6 @@ func main() {
5757
if err := v.runValidation(); err != nil {
5858
log.Fatalf("%v", err)
5959
}
60+
61+
log.Printf("All validation passed!")
6062
}

client/start.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,20 @@ import (
2020
"fmt"
2121
"io/ioutil"
2222
"net/http"
23+
"os"
24+
"path"
2325

2426
"github.com/GoogleCloudPlatform/functions-framework-conformance/events"
2527
cloudevents "github.com/cloudevents/sdk-go/v2"
2628
)
2729

28-
const (
29-
stdoutFile = "serverlog_stdout.txt"
30-
stderrFile = "serverlog_stderr.txt"
30+
var (
31+
defaultStdoutFile = path.Join(os.TempDir(), "serverlog_stdout.txt")
32+
defaultStderrFile = path.Join(os.TempDir(), "serverlog_stderr.txt")
3133
)
3234

3335
type functionServer interface {
34-
Start() (func(), error)
36+
Start(stdoutFile, stderrFile string) (func(), error)
3537
OutputFile() ([]byte, error)
3638
}
3739

client/validate.go

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package main
1717
import (
1818
"encoding/json"
1919
"fmt"
20+
"io/ioutil"
2021
"log"
2122

2223
"github.com/GoogleCloudPlatform/functions-framework-conformance/events"
@@ -39,12 +40,16 @@ type validator struct {
3940
funcServer functionServer
4041
validateMapping bool
4142
functionType string
43+
stdoutFile string
44+
stderrFile string
4245
}
4346

4447
func newValidator(params validatorParams) *validator {
4548
v := validator{
4649
validateMapping: params.validateMapping,
4750
functionType: params.functionType,
51+
stdoutFile: defaultStdoutFile,
52+
stderrFile: defaultStderrFile,
4853
}
4954

5055
if !params.useBuildpacks {
@@ -73,23 +78,43 @@ func newValidator(params validatorParams) *validator {
7378
func (v validator) runValidation() error {
7479
log.Printf("Validating for %s...", *functionType)
7580

76-
shutdown, err := v.funcServer.Start()
81+
shutdown, err := v.funcServer.Start(v.stdoutFile, v.stderrFile)
7782
if shutdown != nil {
7883
defer shutdown()
7984
}
8085

8186
if err != nil {
82-
return fmt.Errorf("unable to start server: %v", err)
87+
return v.errorWithLogsf("unable to start server: %v", err)
8388
}
8489

8590
if err := v.validate("http://localhost:8080"); err != nil {
86-
return fmt.Errorf("Validation failure: %v", err)
91+
return v.errorWithLogsf("validation failure: %v", err)
8792
}
88-
89-
log.Printf("All validation passed!")
9093
return nil
9194
}
9295

96+
func (v validator) errorWithLogsf(errorFmt string, paramsFmts ...interface{}) error {
97+
logs, readErr := v.readLogs()
98+
if readErr != nil {
99+
logs = readErr.Error()
100+
}
101+
return fmt.Errorf("%s, server logs: %s", fmt.Sprintf(errorFmt, paramsFmts...), logs)
102+
}
103+
104+
func (v validator) readLogs() (string, error) {
105+
stdout, err := ioutil.ReadFile(v.stdoutFile)
106+
if err != nil {
107+
return "", fmt.Errorf("could not read stdout file %q: %w", v.stdoutFile, err)
108+
}
109+
110+
stderr, err := ioutil.ReadFile(v.stderrFile)
111+
if err != nil {
112+
return "", fmt.Errorf("could not read stderr file %q: %w", v.stdoutFile, err)
113+
}
114+
115+
return fmt.Sprintf("\n[%s]: '%s'\n[%s]: '%s'", v.stdoutFile, stdout, v.stderrFile, stderr), nil
116+
}
117+
93118
// The HTTP function should copy the contents of the request into the response.
94119
func (v validator) validateHTTP(url string) error {
95120
want := map[string]string{
@@ -146,7 +171,7 @@ func (v validator) validateEvents(url string, inputType, outputType events.Event
146171
}
147172

148173
logStr, err := events.PrintValidationInfos(vis)
149-
log.Printf(logStr)
174+
log.Println(logStr)
150175
return err
151176
}
152177

@@ -189,5 +214,5 @@ func (v validator) validate(url string) error {
189214
log.Printf("Legacy event validation passed!")
190215
return nil
191216
}
192-
return fmt.Errorf("Expected type to be one of 'http', 'cloudevent', or 'legacyevent', got %s", v.functionType)
217+
return fmt.Errorf("expected type to be one of 'http', 'cloudevent', or 'legacyevent', got %s", v.functionType)
193218
}

0 commit comments

Comments
 (0)