Skip to content

Commit

Permalink
feat: add an extension to monitor via docker (#300)
Browse files Browse the repository at this point in the history
Co-authored-by: rick <LinuxSuRen@users.noreply.github.com>
  • Loading branch information
LinuxSuRen and LinuxSuRen authored Dec 1, 2023
1 parent ceebdee commit 1bc6b66
Show file tree
Hide file tree
Showing 38 changed files with 2,011 additions and 77 deletions.
18 changes: 10 additions & 8 deletions .github/testing/core.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
name: atest
api: |
{{default "http://localhost:8080/server.Runner" (env "SERVER")}}
param:
name: "{{randAlpha 6}}"
items:
- name: createSuite
request:
api: /CreateTestSuite
method: POST
body: |
{"name": "{{randAlpha 6}}"}
{"name": "{{.param.name}}"}
- name: suites
request:
api: /GetSuites
Expand All @@ -20,18 +22,18 @@ items:
api: /GetTestSuite
method: POST
body: |
{"name": "{{randAlpha 6}}"}
{"name": "{{.param.name}}"}
expect:
bodyFieldsExpect:
name: ""
name: "{{.param.name}}"
api: ""
- name: UpdateTestSuite
request:
api: /UpdateTestSuite
method: POST
body: |
{
"name": "{{index (keys .suites.data) 0}}",
"name": "{{.param.name}}",
"api": "{{randAlpha 6}}"}
}
- name: DeleteTestSuiteNotFound
Expand All @@ -48,7 +50,7 @@ items:
api: /ListTestCase
method: POST
body: |
{"name": "{{index (keys .suites.data) (randInt 0 (len (keys .suites.data)))}}"}
{"name": "{{.param.name}}"}
- name: list-testcases-not-found
request:
api: /ListTestCase
Expand Down Expand Up @@ -95,7 +97,7 @@ items:
method: POST
body: |
{
"TestSuite": "{{index (keys .suites.data) 0}}",
"TestSuite": "{{.param.name}}",
"TestCase": "{{randAlpha 6}}",
"Generator": "golang"
}
Expand All @@ -117,7 +119,7 @@ items:
method: POST
body: |
{
"TestSuite": "{{index (keys .suites.data) 0}}",
"TestSuite": "{{.param.name}}",
"Generator": "jmeter"
}
expect:
Expand Down Expand Up @@ -155,4 +157,4 @@ items:
api: /DeleteTestSuite
method: POST
body: |
{"name": "{{index (keys .suites.data) 0}}"}
{"name": "{{.param.name}}"}
4 changes: 3 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ RUN CGO_ENABLED=0 go build -v -ldflags "-w -s" -o atest-store-orm extensions/sto
RUN CGO_ENABLED=0 go build -v -ldflags "-w -s" -o atest-store-s3 extensions/store-s3/main.go
RUN CGO_ENABLED=0 go build -v -ldflags "-w -s" -o atest-store-etcd extensions/store-etcd/main.go
RUN CGO_ENABLED=0 go build -v -ldflags "-w -s" -o atest-store-mongodb extensions/store-mongodb/main.go
RUN CGO_ENABLED=0 go build -v -a -ldflags "-w -s" -o atest-store-git extensions/store-git/main.go
RUN CGO_ENABLED=0 go build -v -ldflags "-w -s" -o atest-store-git extensions/store-git/main.go
RUN CGO_ENABLED=0 go build -v -ldflags "-w -s" -o atest-monitor-docker extensions/monitor-docker/main.go

FROM docker.io/library/ubuntu:23.04

Expand All @@ -59,6 +60,7 @@ COPY --from=builder /workspace/atest-store-s3 /usr/local/bin/atest-store-s3
COPY --from=builder /workspace/atest-store-etcd /usr/local/bin/atest-store-etcd
COPY --from=builder /workspace/atest-store-git /usr/local/bin/atest-store-git
COPY --from=builder /workspace/atest-store-mongodb /usr/local/bin/atest-store-mongodb
COPY --from=builder /workspace/atest-monitor-docker /usr/local/bin/atest-monitor-docker
COPY --from=builder /workspace/LICENSE /LICENSE
COPY --from=builder /workspace/README.md /README.md

Expand Down
9 changes: 6 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ build:
mkdir -p bin
rm -rf bin/atest
CGO_ENABLED=0 go build ${TOOLEXEC} -a ${BUILD_FLAG} -o bin/${BINARY} main.go
build-ext: build-ext-git build-ext-orm build-ext-s3 build-ext-etcd build-ext-mongodb
build-ext: build-ext-git build-ext-orm build-ext-s3 build-ext-etcd build-ext-mongodb build-ext-monitor-docker
build-ext-git:
CGO_ENABLED=0 go build -ldflags "-w -s" -o bin/atest-store-git extensions/store-git/main.go
build-ext-orm:
Expand All @@ -31,6 +31,8 @@ build-ext-s3:
CGO_ENABLED=0 go build -ldflags "-w -s" -o bin/atest-store-s3 extensions/store-s3/main.go
build-ext-mongodb:
CGO_ENABLED=0 go build -ldflags "-w -s" -o bin/atest-store-mongodb extensions/store-mongodb/main.go
build-ext-monitor-docker:
CGO_ENABLED=0 go build -ldflags "-w -s" -o bin/atest-monitor-docker extensions/monitor-docker/main.go
build-ui:
cd console/atest-ui && npm i && npm run build-only
embed-ui:
Expand Down Expand Up @@ -67,7 +69,7 @@ run-console:
copy:
sudo cp bin/atest /usr/local/bin/
copy-ext:
sudo cp bin/atest-store-* /usr/local/bin/
sudo cp bin/atest-* /usr/local/bin/
copy-restart: build-embed-ui
atest service stop
make copy
Expand Down Expand Up @@ -123,7 +125,8 @@ grpc:
--go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
pkg/server/server.proto \
pkg/testing/remote/loader.proto
pkg/testing/remote/loader.proto \
pkg/runner/monitor/monitor.proto
grpc-gw:
protoc -I . --grpc-gateway_out . \
--grpc-gateway_opt logtostderr=true \
Expand Down
52 changes: 50 additions & 2 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,22 @@ import (
"io"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"
"time"

"github.com/linuxsuren/api-testing/pkg/apispec"
"github.com/linuxsuren/api-testing/pkg/limit"
"github.com/linuxsuren/api-testing/pkg/runner"
"github.com/linuxsuren/api-testing/pkg/runner/monitor"
"github.com/linuxsuren/api-testing/pkg/testing"
fakeruntime "github.com/linuxsuren/go-fake-runtime"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"golang.org/x/sync/semaphore"
"google.golang.org/grpc"
)

type runOption struct {
Expand All @@ -63,14 +68,15 @@ type runOption struct {
level string
caseItems []string
githubReportOption *runner.GithubPRCommentOption
monitorDocker string

// for internal use
loader testing.Loader
}

func newDefaultRunOption() *runOption {
return &runOption{
reporter: runner.NewMemoryTestReporter(),
reporter: runner.NewMemoryTestReporter(nil, ""),
reportWriter: runner.NewResultWriter(os.Stdout),
loader: testing.NewFileLoader(),
githubReportOption: &runner.GithubPRCommentOption{},
Expand Down Expand Up @@ -112,6 +118,7 @@ See also https://github.com/LinuxSuRen/api-testing/tree/master/sample`,
flags.Int64VarP(&opt.thread, "thread", "", 1, "Threads of the execution")
flags.Int32VarP(&opt.qps, "qps", "", 5, "QPS")
flags.Int32VarP(&opt.burst, "burst", "", 5, "burst")
flags.StringVarP(&opt.monitorDocker, "monitor-docker", "", "", "The docker container name to monitor")
addGitHubReportFlags(flags, opt.githubReportOption)
return
}
Expand Down Expand Up @@ -163,16 +170,56 @@ func (o *runOption) preRunE(cmd *cobra.Command, args []string) (err error) {
}
}

if err == nil {
err = o.startMonitor()
}

o.caseItems = args
return
}

func (o *runOption) startMonitor() (err error) {
if o.monitorDocker == "" {
return
}

var monitorBin string
if monitorBin, err = exec.LookPath("atest-monitor-docker"); err != nil {
return
}

sockFile := os.ExpandEnv(fmt.Sprintf("$HOME/.config/atest/%s.sock", "atest-monitor-docker"))
os.MkdirAll(filepath.Dir(sockFile), 0755)

execer := fakeruntime.DefaultExecer{}
go func(socketURL, plugin string) {
if err = execer.RunCommandWithIO(plugin, "", os.Stdout, os.Stderr, "server", "--socket", socketURL); err != nil {
log.Printf("failed to start %s, error: %v", socketURL, err)
}
}(sockFile, monitorBin)

for i := 0; i < 6; i++ {
_, fErr := os.Stat(sockFile)
if fErr == nil {
break
}
time.Sleep(time.Second)
}

var conn *grpc.ClientConn
monitorServer := fmt.Sprintf("unix://%s", sockFile)
if conn, err = grpc.Dial(monitorServer, grpc.WithInsecure()); err == nil {
o.reporter = runner.NewMemoryTestReporter(monitor.NewMonitorClient(conn), o.monitorDocker)
}
return
}

func (o *runOption) runE(cmd *cobra.Command, args []string) (err error) {
o.startTime = time.Now()
o.context = cmd.Context()
o.limiter = limit.NewDefaultRateLimiter(o.qps, o.burst)
defer func() {
cmd.Printf("consume: %s\n", time.Since(o.startTime).String())
cmd.Printf("\nconsume: %s\n", time.Since(o.startTime).String())
o.limiter.Stop()
}()

Expand All @@ -195,6 +242,7 @@ func (o *runOption) runE(cmd *cobra.Command, args []string) (err error) {
var reportErr error
var results runner.ReportResultSlice
if results, reportErr = o.reporter.ExportAllReportResults(); reportErr == nil {
o.reportWriter.WithResourceUsage(o.reporter.GetResourceUsage())
outputErr := o.reportWriter.Output(results)
println(cmd, outputErr, "failed to Output all reports", outputErr)
}
Expand Down
7 changes: 7 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,13 @@ Connect to [a vault extension](https://github.com/LinuxSuRen/api-testing-secret-
atest server --secret-server localhost:7073
```

## Application monitor
You can get the resource usage in the report through Docker:

```shell
atest run -p sample/testsuite-gitlab.yaml --monitor-docker test --report md
```

## Verify

| Item | Description |
Expand Down
56 changes: 56 additions & 0 deletions extensions/monitor-docker/cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
MIT License
Copyright (c) 2023 API Testing Authors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

package cmd

import (
"github.com/docker/cli/cli/command"
"github.com/linuxsuren/api-testing/extensions/monitor-docker/pkg"
ext "github.com/linuxsuren/api-testing/pkg/extension"
"github.com/spf13/cobra"
)

func NewRootCommand(dockerCli command.Cli) (c *cobra.Command) {
opt := options{
dockerCli: dockerCli,
Extension: ext.NewExtension("docker", "monitor", 7074),
}
c = &cobra.Command{
Use: "server",
RunE: opt.runE,
}
opt.AddFlags(c.Flags())
return
}

type options struct {
*ext.Extension
dockerCli command.Cli
}

func (o *options) runE(c *cobra.Command, _ []string) (err error) {
remoteServer := pkg.NewRemoteServer(o.dockerCli)
err = ext.CreateMonitor(o.Extension, c, remoteServer)
return
}
Loading

0 comments on commit 1bc6b66

Please sign in to comment.