Skip to content

Commit

Permalink
Merge pull request #185 from yarpc/dev
Browse files Browse the repository at this point in the history
Release version 0.10.0
  • Loading branch information
prashantv authored Apr 7, 2017
2 parents ae1abf6 + 7637ede commit 8a6bd0a
Show file tree
Hide file tree
Showing 35 changed files with 1,816 additions and 91 deletions.
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
vendor

10 changes: 10 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ env:
global:
- GO15VENDOREXPERIMENT=1
- TEST_TIMEOUT_SCALE=10
- GITHUB_USER=prashantv
- secure: paMlkVWaAi0NACXU2oAcSZQugszfb8sALV/FrtXmWtCen42n/6JXLHU4EHNwnLUDo7ZtgTniEPzBXW4GPSMJyyjyk55T4mWmbeMrELfNpHATmIhTRA6xP8AVHwph14i9jDXNLfiGsCZEkpyBfEOsUHc2jS7wSCA2yXBD6OFSoFGWwrpHMrUO0UHXyKGTGKsQrSQMkIaZ9WOXW0S6FRxjfUTLG9oCFfTxM7LGsz26YYI61nRSPnecitmoKVOCj3toMmg8vG6EwsBwDLggLblc70Fw5fggWeTUpvFUrczzqiWq2Sv61FIhMaT1OsO990w5B5BAODoa/L/G0OExd66GSBGHeu7vudIncKoE2jWxinFQzrJ21cEIyT+1LE0ABC4Zcb51KMzm/Alkn4oaSH2X9al/xQjTrVYGaEJdUu62JzkV5SuUrR+3ZzSy9MaUP8CAaP2W7MlyrjNewoO53BkkDtfh0/EbQFWGgE6lULkWwL4JX9qDkJWB5O7aHCM/fjfVRxODsgUfKksabeycabp1mqLQovQhVLLkk/DH66HKFIAO+EHg+EEQA3Z0PJuOf6zqDgHYxj9fXGvega1Yhuecnkej02iEBsuFM+WMDvAXMj5kWwMy5XhFc57ZJtVoFFA0HEjWJessbQNX3ci919wJQuSwI/5HG5ATg2o3Pb5KtD4=

cache:
directories:
Expand All @@ -20,3 +22,11 @@ install:
script:
- make test_ci
- travis_retry goveralls -coverprofile=cover.out -service=travis-ci

deploy:
- provider: script
script: scripts/release.sh $TRAVIS_TAG
skip_cleanup: true
on:
go: 1.8
tags: true
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Changelog
=========

# 0.10.0

* Support disabling Thrift envelopes from YAML templates.
* Add template argument support, which allows passing parameters
to YAML templates.

# 0.9.0

* Support for custom peer providers to provide a list of peers such as
Expand Down
13 changes: 13 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM golang:1.7-alpine

COPY . /go/src/github.com/yarpc/yab

RUN apk update
RUN apk add git

RUN cd /go/src/github.com/yarpc/yab && go get github.com/Masterminds/glide
RUN cd /go/src/github.com/yarpc/yab && glide install
RUN cd /go/src/github.com/yarpc/yab && go install .

ENTRYPOINT ["yab"]

1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ install_ci: install
go get github.com/wadey/gocovmerge
go get github.com/mattn/goveralls
go get golang.org/x/tools/cmd/cover
go get github.com/tcnksm/ghr


.PHONY: docs
Expand Down
15 changes: 12 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ intended for Thrift applications but supports other encodings like JSON and
binary (raw). It can be used in a curl-like fashion when benchmarking features
are disabled.
yab includes a full man page (man yab), which is also available online:
http://yarpc.github.io/yab/man.html
Application Options:
--version Displays the application version
Expand All @@ -38,8 +41,9 @@ Request Options:
JSON, raw. Defaults to Thrift if the method
contains '::' or a Thrift file is specified
-t, --thrift= Path of the .thrift file
-m, --method= The full Thrift method name (Svc::Method) to
--procedure= The full Thrift method name (Svc::Method) to
invoke
-m, --method= Alias for procedure
-r, --request= The request body, in JSON or YAML format
-f, --file= Path of a file containing the request body in
JSON or YAML
Expand All @@ -54,6 +58,10 @@ Request Options:
--timeout= The timeout for each request. E.g., 100ms,
0.5s, 1s. If no unit is specified,
milliseconds are assumed. (default: 1s)
-y, --yaml-template= Send a tchannel request specified by a YAML
template
-A, --arg= A list of key-value template arguments,
specified as -A foo:bar -A user:me
--disable-thrift-envelope Disables Thrift envelopes (disabled by default
for TChannel)
--multiplexed-thrift Enables the Thrift TMultiplexedProtocol used
Expand All @@ -63,8 +71,9 @@ Request Options:
Transport Options:
-s, --service= The TChannel/Hyperbahn service name
-p, --peer= The host:port of the service to call
-P, --peer-list= Path of a JSON or YAML file containing a list
of host:ports
-P, --peer-list= Path or URL of a JSON, YAML, or flat file
containing a list of host:ports. -P? for
supported protocols.
--caller= Caller will override the default caller name
(which is yab-$USER).
--rk= The routing key overrides the service name
Expand Down
48 changes: 48 additions & 0 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,54 @@ Or it can be loaded from a file using -f or --file:
$ yab -p localhost:9787 -t kv.thrift kv KeyValue::Get --file req.yaml
Request options can also be specified in a YAML file, e.g., get.yab:
service: kv
peer: localhost:9787
method: KeyValue::get
thrift: kv.thrift
request:
key: hello
The above YAML file represents the same request as the command above, and can
be run using yab -y get.yab.
You can make the request by directly executing the file (./get.yab) if you
add a shebang and mark the file as executable:
#!/usr/bin/env yab -y
service: kv
peer: localhost:9787
method: KeyValue::get
thrift: kv.thrift
request:
key: hello
YAML templates can use arguments using ${ARGNAME:default_value} in the body,
which can be specified on the command line using -A. If an argument is not
specified on the command line, then the default value is used. For example,
we can update the YAML template to take an argument for the key:
#!/usr/bin/env yab -y
service: kv
peer: localhost:9787
method: KeyValue::get
thrift: kv.thrift
request:
key: ${key:hello}
If no key is specified on the command line, the default value of "hello" is
used as the key. However we can specify the key on the command line:
$ ./get.yab -A key:world
A YAML template may have multiple keys and multiple keys can be specified on
the command line:
$ ./set.yab -A key:hello -A value:world
Binary data can be specified in one of many ways:
* As a string or an array of bytes: "data" or [100, 97, 116, 97]
* As base64: {"base64": "ZGF0YQ=="}
Expand Down
23 changes: 15 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,18 @@ func getOptions(args []string, out output) (*Options, error) {
parser.ShortDescription = "yet another benchmarker"
parser.LongDescription = `
yab is a benchmarking tool for TChannel and HTTP applications. It's primarily intended for Thrift applications but supports other encodings like JSON and binary (raw). It can be used in a curl-like fashion when benchmarking features are disabled.
yab includes a full man page (man yab), which is also available online: http://yarpc.github.io/yab/man.html
`

// Read defaults if they're available, before we change the group names.
if err := parseDefaultConfigs(parser); err != nil {
return nil, fmt.Errorf("error reading defaults: %v", err)
}

overrideDefaults(opts, args)
if err := overrideDefaults(opts, args); err != nil {
return nil, err
}

setGroupDescs(parser, "request", "Request Options", toGroff(_reqOptsDesc))
setGroupDescs(parser, "transport", "Transport Options", toGroff(_transportOptsDesc))
Expand Down Expand Up @@ -193,17 +197,26 @@ func parseAndRun(out output) {
// E.g., if the defaults has a peer list file, and the user has specifed
// a peer through the command line, then the final options should only
// contain the peer specified in the args.
func overrideDefaults(defaults *Options, args []string) {
func overrideDefaults(defaults *Options, args []string) error {
argsParser, argsOnly := newParser()
argsParser.ParseArgs(args)

// If there's a YAML request specified, read that now.
if argsOnly.ROpts.YamlTemplate != "" {
if err := readYAMLFile(argsOnly.ROpts.YamlTemplate, argsOnly.ROpts.TemplateArgs, defaults); err != nil {
return fmt.Errorf("failed to read yaml template: %v", err)
}
}

// Clear default peers if the user has specified peer options in args.
if len(argsOnly.TOpts.Peers) > 0 {
defaults.TOpts.PeerList = ""
}
if len(argsOnly.TOpts.PeerList) > 0 {
defaults.TOpts.Peers = nil
}

return nil
}

// findBestConfigFile finds the best config file to use. An empty string will be
Expand Down Expand Up @@ -249,12 +262,6 @@ func runWithOptions(opts Options, out output) {
return
}

if opts.ROpts.YamlTemplate != "" {
if err := readYAMLRequest(&opts); err != nil {
out.Fatalf("Failed while reading yaml template: %v\n", err)
}
}

reqInput, err := getRequestInput(opts.ROpts.RequestJSON, opts.ROpts.RequestFile)
if err != nil {
out.Fatalf("Failed while loading body input: %v\n", err)
Expand Down
113 changes: 113 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -936,3 +936,116 @@ func TestMainSupportedPeerProviderSchemes(t *testing.T) {
assert.Contains(t, contents, "file\n", "Expected file protocol support")
assert.NotContains(t, contents, "\n\n", "Expected no blank lines")
}

func TestOverrideDefaultsFails(t *testing.T) {
_, out := getOutput(t)
_, err := getOptions([]string{"-y", "testdata/templates/invalid.yaml"}, out)
require.Error(t, err, "Invalid YAML template should fail to parse")
assert.Contains(t, err.Error(), "failed to read yaml template")
}

func TestOptionsInheritance(t *testing.T) {
originalConfigHome := os.Getenv(_configHomeEnv)
defer os.Setenv(_configHomeEnv, originalConfigHome)

tests := []struct {
args []string
yaml string
defaults string
wantPeers []string
wantPeerList string
wantProcedure string
wantTimeout time.Duration
}{
{
defaults: "peer=1.1.1.1",
yaml: "",
wantPeers: []string{"1.1.1.1"},
},
{
defaults: "peer=1.1.1.1",
args: []string{"--peer", "2.2.2.2"},
wantPeers: []string{"2.2.2.2"},
},
{
defaults: "peer=1.1.1.1",
yaml: "peer: 2.2.2.2",
args: []string{"--peer", "3.3.3.3"},
wantPeers: []string{"3.3.3.3"},
},
{
defaults: "peer-list=http://foo",
yaml: "peer: 1.1.1.1",
wantPeers: []string{"1.1.1.1"},
},
{
defaults: "peer=1.1.1.1",
yaml: "peerList: http://foo",
wantPeerList: "http://foo",
},
{
defaults: "peer=1.1.1.1",
yaml: "peerList: http://foo",
args: []string{"--peer-list", "http://bar"},
wantPeerList: "http://bar",
},
{
defaults: "peer=1.1.1.1",
yaml: "peerList: http://foo",
args: []string{"--peer", "2.2.2.2"},
wantPeers: []string{"2.2.2.2"},
},
{
defaults: "peer=1.1.1.1",
yaml: "peer: 2.2.2.2",
args: []string{"--peer-list", "http://bar"},
wantPeerList: "http://bar",
},
{
defaults: "method=foo",
wantProcedure: "foo",
},
{
defaults: "procedure=foo",
yaml: "procedure: bar",
wantProcedure: "bar",
},
{
defaults: "procedure=foo",
yaml: "procedure: bar",
args: []string{"--procedure", "baz"},
wantProcedure: "baz",
},
{
defaults: "timeout=2s",
wantTimeout: 2 * time.Second,
},
}

xdgBase, err := ioutil.TempDir("", "options")
require.NoError(t, err, "Failed to create temp dir")
os.Setenv(_configHomeEnv, xdgBase)

xdgFile := filepath.Join(xdgBase, "yab", "defaults.ini")
require.NoError(t, os.MkdirAll(filepath.Dir(xdgFile), 0777), "Failed to create yab XDG dir")

for _, tt := range tests {
msg := fmt.Sprintf("Test case: %+v", tt)
err := ioutil.WriteFile(xdgFile, []byte(tt.defaults), 0666)
require.NoError(t, err, "Failed to write out defaults.ini")

_, out := getOutput(t)

tt.args = append(tt.args, "-y", writeFile(t, "yaml", tt.yaml))
opts, err := getOptions(tt.args, out)
require.NoError(t, err, "getOptions failed")

assert.Equal(t, tt.wantPeers, opts.TOpts.Peers, msg)
assert.Equal(t, tt.wantPeerList, opts.TOpts.PeerList, msg)
assert.Equal(t, tt.wantProcedure, opts.ROpts.Procedure, "procedure")

if tt.wantTimeout != 0 {
assert.Equal(t, tt.wantTimeout, opts.ROpts.Timeout.Duration(), "timeout")
}
}
}
Loading

0 comments on commit 8a6bd0a

Please sign in to comment.