Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix egbuilder bug, add integration tests for egbuilder #1164

Merged
merged 2 commits into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Next Next commit
fix egbuilder bug, add integration tests for egbuilder
  • Loading branch information
suchen-sci committed Dec 8, 2023
commit 6b4577e03feaa5896cafa25bf24af6667539b673
17 changes: 15 additions & 2 deletions build/test/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,20 @@ import (
"strings"
)

func egctlCmd(args ...string) *exec.Cmd {
func egctlWithServer(server string, args ...string) *exec.Cmd {
egctl := os.Getenv("EGCTL")
if egctl == "" {
egctl = "egctl"
}
cmd := exec.Command(egctl, args...)
cmd.Args = append(cmd.Args, "--server", "http:https://127.0.0.1:12381")
cmd.Args = append(cmd.Args, "--server", server)
return cmd
}

func egctlCmd(args ...string) *exec.Cmd {
return egctlWithServer("http:https://127.0.0.1:12381", args...)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use the default option http:https://127.0.0.1:2381 in server.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good question!
this integration test runs with primary-single instance in example folder. it uses 12381 as its api address...

}

func runCmd(cmd *exec.Cmd) (string, string, error) {
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
Expand Down Expand Up @@ -110,3 +114,12 @@ func matchTable(array []string, output string) bool {
// Check if the regular expression matches the output string
return re.MatchString(output)
}

func egbuilderCmd(args ...string) *exec.Cmd {
egbuilder := os.Getenv("EGBUILDER")
if egbuilder == "" {
egbuilder = "egbuilder"
}
cmd := exec.Command(egbuilder, args...)
return cmd
}
229 changes: 229 additions & 0 deletions build/test/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"io"
"net/http"
"os"
"os/exec"
"path/filepath"
"strings"
"sync/atomic"
Expand Down Expand Up @@ -1076,3 +1077,231 @@ filters:
assert.Nil(err)
assert.Equal("hello from websocket", string(data))
}

func TestEgbuilder(t *testing.T) {
assert := assert.New(t)

tempDir, err := os.MkdirTemp("", "easegress-test")
require.Nil(t, err)
defer os.RemoveAll(tempDir)

// init a new plugin repo
initCmd := egbuilderCmd(
"init",
"--repo", "github.com/test/repo",
"--filters=MyFilter1",
"--controllers=MyController1,MyController2",
)
initCmd.Dir = tempDir
stdout, stderr, err := runCmd(initCmd)
fmt.Printf("init stdout:\n%s\n", stdout)
fmt.Printf("init stderr:\n%s\n", stderr)
assert.NoError(err)

// add a new filters and controllers
addCmd := egbuilderCmd(
"add",
"--filters=MyFilter2",
"--controllers=MyController3",
)
addCmd.Dir = tempDir
stdout, stderr, err = runCmd(addCmd)
fmt.Printf("add stdout:\n%s\n", stdout)
fmt.Printf("add stderr:\n%s\n", stderr)
assert.NoError(err)

// build easegress with new plugins
buildConfig := `
plugins:
- module: github.com/test/repo
version: ""
replacement: %s

output: "%s/easegress-server"
`
buildConfig = fmt.Sprintf(buildConfig, tempDir, tempDir)
err = os.WriteFile(filepath.Join(tempDir, "build.yaml"), []byte(buildConfig), os.ModePerm)
assert.NoError(err)

buildCmd := egbuilderCmd(
"build",
"-f",
"build.yaml",
)
buildCmd.Dir = tempDir
stdout, stderr, err = runCmd(buildCmd)
fmt.Printf("build stdout:\n%s\n", stdout)
fmt.Printf("build stderr:\n%s\n", stderr)
assert.NoError(err)

// run easegress with new plugins
egserverConfig := `
name: egbuilder
cluster-name: egbuilder-test
cluster-role: primary
cluster:
listen-peer-urls:
- http:https://localhost:22380
listen-client-urls:
- http:https://localhost:22379
advertise-client-urls:
- http:https://localhost:22379
initial-advertise-peer-urls:
- http:https://localhost:22380
initial-cluster:
- egbuilder: http:https://localhost:22380
api-addr: 127.0.0.1:22381
`
apiURL := "http:https://127.0.0.1:22381"
err = os.WriteFile(filepath.Join(tempDir, "config.yaml"), []byte(egserverConfig), os.ModePerm)
assert.Nil(err)

runEgCmd := exec.Command(
filepath.Join(tempDir, "easegress-server"),
"--config-file",
"config.yaml",
)
runEgCmd.Dir = tempDir
var stdoutBuf, stderrBuf bytes.Buffer
runEgCmd.Stdout = &stdoutBuf
runEgCmd.Stderr = &stderrBuf
err = runEgCmd.Start()
assert.Nil(err)
defer runEgCmd.Process.Kill()

started := checkServerStart(func() *http.Request {
req, err := http.NewRequest(http.MethodGet, apiURL+"/apis/v2/healthz", nil)
assert.Nil(err)
return req
})
assert.True(started)

egctl := func(args ...string) *exec.Cmd {
return egctlWithServer(apiURL, args...)
}

// create, apply, delete new controllers
controllers := `
name: c1
kind: MyController1

---

name: c2
kind: MyController2

---

name: c3
kind: MyController3
`
controllerNames := []string{"c1", "c2", "c3"}
controllerKinds := []string{"MyController1", "MyController2", "MyController3"}

cmd := egctl("create", "-f", "-")
cmd.Stdin = strings.NewReader(controllers)
stdout, stderr, err = runCmd(cmd)
fmt.Printf("egctl create stdout:\n%s\n", stdout)
assert.Contains(stdout, "create MyController1 c1 successfully")
assert.Contains(stdout, "create MyController2 c2 successfully")
assert.Contains(stdout, "create MyController3 c3 successfully")
assert.Empty(stderr)
assert.NoError(err)

cmd = egctl("get", "all")
stdout, stderr, err = runCmd(cmd)
for i := range controllerNames {
assert.Contains(stdout, controllerNames[i])
assert.Contains(stdout, controllerKinds[i])
}
assert.Empty(stderr)
assert.NoError(err)

cmd = egctl("apply", "-f", "-")
cmd.Stdin = strings.NewReader(controllers)
stdout, stderr, err = runCmd(cmd)
fmt.Printf("egctl apply stdout:\n%s\n", stdout)
assert.Contains(stdout, "update MyController1 c1 successfully")
assert.Contains(stdout, "update MyController2 c2 successfully")
assert.Contains(stdout, "update MyController3 c3 successfully")
assert.Empty(stderr)
assert.NoError(err)

for i := range controllerNames {
cmd = egctl("delete", controllerKinds[i], controllerNames[i])
stdout, stderr, err = runCmd(cmd)
fmt.Printf("egctl delete stdout:\n%s\n", stdout)
assert.Contains(stdout, fmt.Sprintf("delete %s %s successfully", controllerKinds[i], controllerNames[i]))
assert.Empty(stderr)
assert.NoError(err)
}

cmd = egctl("get", "all")
stdout, stderr, err = runCmd(cmd)
for i := range controllerNames {
assert.NotContains(stdout, controllerNames[i])
assert.NotContains(stdout, controllerKinds[i])
}
assert.Empty(stderr)
assert.NoError(err)

// create, apply, delete new filters
filters := `
name: httpserver
kind: HTTPServer
port: 22399
rules:
- paths:
- backend: pipeline

---

name: pipeline
kind: Pipeline
flow:
- filter: filter1
- filter: filter2
- filter: mock
filters:
- name: filter1
kind: MyFilter1
- name: filter2
kind: MyFilter2
- name: mock
kind: ResponseBuilder
template: |
statusCode: 200
body: "body from response builder"
`

cmd = egctl("create", "-f", "-")
cmd.Stdin = strings.NewReader(filters)
stdout, stderr, err = runCmd(cmd)
fmt.Printf("egctl create stdout:\n%s\n", stdout)
assert.Empty(stderr)
assert.NoError(err)

cmd = egctl("apply", "-f", "-")
cmd.Stdin = strings.NewReader(filters)
stdout, stderr, err = runCmd(cmd)
fmt.Printf("egctl apply stdout:\n%s\n", stdout)
assert.Empty(stderr)
assert.NoError(err)

started = checkServerStart(func() *http.Request {
req, err := http.NewRequest(http.MethodGet, "http:https://127.0.0.1:22399", nil)
assert.Nil(err)
return req
})
assert.True(started)

req, err := http.NewRequest(http.MethodGet, "http:https://127.0.0.1:22399", nil)
assert.Nil(err)
resp, err := http.DefaultClient.Do(req)
assert.Nil(err)
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
assert.Nil(err)
// get this body means our pipeline is working.
assert.Equal("body from response builder", string(data))
}
3 changes: 2 additions & 1 deletion build/test/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pushd $SCRIPTPATH"/../../example" > /dev/null
EXAMPLEDIR="$SCRIPTPATH"/../../example
PRIMARYDIR=$EXAMPLEDIR"/primary-single"
EGCTL=$PRIMARYDIR"/bin/egctl"
EGBUILDER=$PRIMARYDIR"/bin/egbuilder"

# target file related define.
server="primary-single/bin/easegress-server"
Expand Down Expand Up @@ -75,7 +76,7 @@ else
fi

# run go test
env EGCTL=$EGCTL go test -v $SCRIPTPATH
env EGCTL=$EGCTL EGBUILDER=$EGBUILDER go test -v $SCRIPTPATH

popd > /dev/null
exit 0
2 changes: 1 addition & 1 deletion cmd/builder/gen/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func defineFilterMethods(file *j.File, info *FilterInfo) {
nameFunc := receiver()
nameFunc.Name = "Name"
nameFunc.Returns = []j.Code{j.String()}
nameFunc.Block = []j.Code{j.Return(j.Lit(info.Name))}
nameFunc.Block = []j.Code{j.Return(j.Id(info.ReceiverName).Dot("spec").Dot("Name()"))}
file.Add(nameFunc.Def())

// define filter Kind method
Expand Down
2 changes: 1 addition & 1 deletion pkg/object/pipeline/pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ func (p *Pipeline) reload(previousGeneration *Pipeline) {

// add the filter to pipeline, and if the pipeline does not define a
// flow, append it to the flow we just created.
p.filters[filter.Name()] = filter
p.filters[spec.Name()] = filter
if len(p.spec.Flow) == 0 {
flow = append(flow, FlowNode{FilterName: spec.Name()})
}
Expand Down