Skip to content

Commit da51f06

Browse files
committed
Merge branch 'main' into ccipv2-chaos-suite
2 parents 9f8665b + 49bbad9 commit da51f06

30 files changed

+16845
-1420
lines changed

.github/workflows/framework-golden-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ jobs:
8686
with:
8787
go-version: 1.23
8888
- name: Cache Go modules
89-
uses: actions/cache@v3
89+
uses: actions/cache@v4
9090
with:
9191
path: |
9292
~/.cache/go-build

.github/workflows/lint.yaml

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,13 @@ jobs:
8282
- name: Check out Code
8383
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
8484
- name: Install Go
85-
uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-go@d2f9642bcc24a73400568756f24b72c188ac7a9a # v2.3.31
85+
uses: smartcontractkit/.github/actions/setup-golang@3835daadbcefcae06d12dc42a405a856c980d2cc
8686
with:
87-
test_download_vendor_packages_command: cd ${{ matrix.project.path }} && go mod download
88-
go_mod_path: ${{ matrix.project.path }}go.mod
89-
cache_key_id: ctf-go-${{ matrix.project.name }}
90-
cache_restore_only: 'false'
87+
go-version-file: ${{ matrix.project.path }}go.mod
88+
use-go-cache: true
89+
go-cache-dep-path: ${{ matrix.project.path }}go.sum
9190
- name: golangci-lint ${{ needs.tools.outputs.golangci-lint-version }}
92-
uses: golangci/golangci-lint-action@9d1e0624a798bb64f6c3cea93db47765312263dc # v5.1.0
91+
uses: golangci/golangci-lint-action@051d91933864810ecd5e2ea2cfd98f6a5bca5347 # v6.3.2
9392
with:
9493
version: v${{ needs.tools.outputs.golangci-lint-version }}
9594
args: --out-format checkstyle:golangci-lint-report.xml
@@ -113,12 +112,11 @@ jobs:
113112
- name: Check out Code
114113
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
115114
- name: Install Go
116-
uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-go@d2f9642bcc24a73400568756f24b72c188ac7a9a # v2.3.31
115+
uses: smartcontractkit/.github/actions/setup-golang@3835daadbcefcae06d12dc42a405a856c980d2cc
117116
with:
118-
test_download_vendor_packages_command: cd lib && go mod download
119-
go_mod_path: ./lib/go.mod
120-
cache_key_id: ctf-go
121-
cache_restore_only: 'false'
117+
go-version-file: ./lib/go.mod
118+
use-go-cache: true
119+
go-cache-dep-path: ./lib/go.sum
122120
- name: Write Go List
123121
working-directory: lib
124122
run: go list -json -deps ./... > ../go.list

CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
* @sebawo @smartcontractkit/test-tooling-team
1+
* @smartcontractkit/test-tooling-team

parrot/.goreleaser.yaml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
version: 2
33
project_name: parrot
44

5+
dist: parrot/dist
6+
57
monorepo:
68
tag_prefix: parrot/
79
dir: parrot
@@ -20,8 +22,7 @@ builds:
2022
goarch:
2123
- amd64
2224
- arm64
23-
ldflags:
24-
- '-s -w'
25+
binary: parrot
2526

2627
archives:
2728
- formats: ['binary']
@@ -32,6 +33,7 @@ dockers:
3233
goarch: amd64
3334
image_templates:
3435
- '{{ .Env.IMG_PRE }}/parrot:{{ .Tag }}-amd64'
36+
- '{{ .Env.IMG_PRE }}/parrot:latest-amd64'
3537
build_flag_templates:
3638
- --platform=linux/amd64
3739
- --pull
@@ -44,6 +46,7 @@ dockers:
4446
goarch: arm64
4547
image_templates:
4648
- '{{ .Env.IMG_PRE }}/parrot:{{ .Tag }}-arm64'
49+
- '{{ .Env.IMG_PRE }}/parrot:latest-arm64'
4750
build_flag_templates:
4851
- --platform=linux/arm64
4952
- --pull
@@ -57,7 +60,11 @@ docker_manifests:
5760
image_templates:
5861
- '{{ .Env.IMG_PRE }}/parrot:{{ .Tag }}-amd64'
5962
- '{{ .Env.IMG_PRE }}/parrot:{{ .Tag }}-arm64'
63+
- name_template: '{{ .Env.IMG_PRE }}/parrot:latest'
64+
image_templates:
65+
- '{{ .Env.IMG_PRE }}/parrot:latest-amd64'
66+
- '{{ .Env.IMG_PRE }}/parrot:latest-arm64'
6067

6168
before:
6269
hooks:
63-
- sh -c "cd parrot && go mod tidy"
70+
- sh -c "cd parrot && go mod tidy"

parrot/Dockerfile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
FROM scratch
2+
23
COPY parrot /parrot
3-
ENTRYPOINT [ "parrot", "-port", "9090", "-t" ]
4+
ENV PARROT_PORT 80
5+
ENV PARROT_TRACE true
6+
EXPOSE 80
7+
ENTRYPOINT [ "/parrot" ]

parrot/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,5 @@ fuzz:
3636
.PHONY: build
3737
build:
3838
cd .. && goreleaser release --snapshot --clean -f ./parrot/.goreleaser.yaml
39+
echo "Build done, check in parrot/dist for binaries"
3940

parrot/client.go

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package parrot
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
7+
"github.com/go-resty/resty/v2"
8+
)
9+
10+
// Client interacts with a parrot server
11+
type Client struct {
12+
restyClient *resty.Client
13+
}
14+
15+
// NewClient creates a new client for a parrot server running at the given url.
16+
func NewClient(url string) *Client {
17+
restyC := resty.New()
18+
restyC.SetBaseURL(url)
19+
return &Client{
20+
restyClient: restyC,
21+
}
22+
}
23+
24+
// Health returns the health of the server
25+
func (c *Client) Healthy() (bool, error) {
26+
resp, err := c.restyClient.R().Get(HealthRoute)
27+
if err != nil {
28+
return false, err
29+
}
30+
return resp.StatusCode() == http.StatusOK, nil
31+
}
32+
33+
// Routes returns all the routes registered on the server
34+
func (c *Client) Routes() ([]*Route, error) {
35+
routes := []*Route{}
36+
resp, err := c.restyClient.R().SetResult(&routes).Get(RoutesRoute)
37+
if err != nil {
38+
return nil, err
39+
}
40+
if resp.StatusCode() != http.StatusOK {
41+
return nil, fmt.Errorf("failed to get routes, got %d status code: %s", resp.StatusCode(), string(resp.Body()))
42+
}
43+
return routes, nil
44+
}
45+
46+
// CallRoute calls a route on the server
47+
func (c *Client) CallRoute(method, path string) (*resty.Response, error) {
48+
return c.restyClient.R().Execute(method, path)
49+
}
50+
51+
// RegisterRoute registers a route on the server
52+
func (c *Client) RegisterRoute(route *Route) error {
53+
resp, err := c.restyClient.R().SetBody(route).Post(RoutesRoute)
54+
if err != nil {
55+
return err
56+
}
57+
if resp.StatusCode() != http.StatusCreated {
58+
return fmt.Errorf("failed to register route, got %d status code: %s", resp.StatusCode(), string(resp.Body()))
59+
}
60+
return nil
61+
}
62+
63+
// DeleteRoute deletes a route on the server
64+
func (c *Client) DeleteRoute(route *Route) error {
65+
resp, err := c.restyClient.R().SetBody(route).Delete(RoutesRoute)
66+
if err != nil {
67+
return err
68+
}
69+
if resp.StatusCode() != http.StatusNoContent {
70+
return fmt.Errorf("failed to delete route, got %d status code: %s", resp.StatusCode(), string(resp.Body()))
71+
}
72+
return nil
73+
}
74+
75+
// RegisterRecorder registers a recorder on the server
76+
func (c *Client) RegisterRecorder(recorder *Recorder) error {
77+
resp, err := c.restyClient.R().SetBody(recorder).Post(RecorderRoute)
78+
if err != nil {
79+
return err
80+
}
81+
if resp.StatusCode() != http.StatusCreated {
82+
return fmt.Errorf("failed to register recorder, got %d status code: %s", resp.StatusCode(), string(resp.Body()))
83+
}
84+
return nil
85+
}
86+
87+
// Recorders returns all the recorders registered on the server
88+
func (c *Client) Recorders() ([]string, error) {
89+
recorders := []string{}
90+
resp, err := c.restyClient.R().SetResult(&recorders).Get(RecorderRoute)
91+
if err != nil {
92+
return nil, err
93+
}
94+
if resp.StatusCode() != http.StatusOK {
95+
return nil, fmt.Errorf("failed to get recorders, got %d status code: %s", resp.StatusCode(), string(resp.Body()))
96+
}
97+
return recorders, nil
98+
}

parrot/cmd/main.go

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"context"
55
"os"
66
"os/signal"
7+
"strconv"
8+
"strings"
79
"syscall"
810
"time"
911

@@ -26,6 +28,31 @@ func main() {
2628
rootCmd := &cobra.Command{
2729
Use: "parrot",
2830
Short: "A server that can register and parrot back dynamic requests",
31+
PreRun: func(cmd *cobra.Command, args []string) {
32+
// Check environment variables if flags are not set
33+
if !cmd.Flags().Changed("port") {
34+
if envPort, err := strconv.Atoi(os.Getenv("PARROT_PORT")); err == nil {
35+
port = envPort
36+
}
37+
}
38+
if !cmd.Flags().Changed("debug") {
39+
debug = os.Getenv("PARROT_DEBUG") == "true"
40+
}
41+
if !cmd.Flags().Changed("trace") {
42+
trace = os.Getenv("PARROT_TRACE") == "true"
43+
}
44+
if !cmd.Flags().Changed("silent") {
45+
silent = os.Getenv("PARROT_SILENT") == "true"
46+
}
47+
if !cmd.Flags().Changed("json") {
48+
json = os.Getenv("PARROT_JSON") == "true"
49+
}
50+
if !cmd.Flags().Changed("recorders") {
51+
if envRecorders := os.Getenv("PARROT_RECORDERS"); envRecorders != "" {
52+
recorders = strings.Split(envRecorders, ",")
53+
}
54+
}
55+
},
2956
RunE: func(cmd *cobra.Command, args []string) error {
3057
options := []parrot.ServerOption{parrot.WithPort(port)}
3158
logLevel := zerolog.InfoLevel
@@ -47,7 +74,7 @@ func main() {
4774
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
4875
defer cancel()
4976

50-
p, err := parrot.Wake(options...)
77+
p, err := parrot.NewServer(options...)
5178
if err != nil {
5279
return err
5380
}
@@ -63,12 +90,12 @@ func main() {
6390
},
6491
}
6592

66-
rootCmd.Flags().IntVarP(&port, "port", "p", 0, "Port to run the parrot on")
67-
rootCmd.Flags().BoolVarP(&debug, "debug", "d", false, "Enable debug output")
68-
rootCmd.Flags().BoolVarP(&trace, "trace", "t", false, "Enable trace and debug output")
69-
rootCmd.Flags().BoolVarP(&silent, "silent", "s", false, "Disable all output")
70-
rootCmd.Flags().BoolVarP(&json, "json", "j", false, "Output logs in JSON format")
71-
rootCmd.Flags().StringSliceVarP(&recorders, "recorders", "r", nil, "Existing recorders to use")
93+
rootCmd.Flags().IntVarP(&port, "port", "p", 0, "Port to run the parrot on (env: PARROT_PORT)")
94+
rootCmd.Flags().BoolVarP(&debug, "debug", "d", false, "Enable debug output (env: PARROT_DEBUG)")
95+
rootCmd.Flags().BoolVarP(&trace, "trace", "t", false, "Enable trace and debug output (env: PARROT_TRACE)")
96+
rootCmd.Flags().BoolVarP(&silent, "silent", "s", false, "Disable all output (env: PARROT_SILENT)")
97+
rootCmd.Flags().BoolVarP(&json, "json", "j", false, "Output logs in JSON format (env: PARROT_JSON)")
98+
rootCmd.Flags().StringSliceVarP(&recorders, "recorders", "r", nil, "Existing recorders to use (env: PARROT_RECORDERS)")
7299

73100
if err := rootCmd.Execute(); err != nil {
74101
log.Error().Err(err).Msg("error executing command")

0 commit comments

Comments
 (0)