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

[tools] CLI tool to simplify some tasks, and eliminate the curl commands from the docs #2097

Merged
merged 70 commits into from
Apr 15, 2020
Merged
Show file tree
Hide file tree
Changes from 66 commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
f3b7ccf
[script] remove DS_PROMETHEUS variable interpolation syntax in Docker…
xmcqueen Dec 12, 2019
062e74d
Merge remote-tracking branch 'upstream/master'
xmcqueen Jan 4, 2020
96f2d6e
start of tool for some operational tasks
xmcqueen Jan 5, 2020
d01a473
looks like yaml inputs works nicely
xmcqueen Jan 7, 2020
30fd1a5
cleaned up a lot and added many api calls
xmcqueen Jan 7, 2020
040a2b4
added placement init
xmcqueen Jan 8, 2020
8e86a94
factored
xmcqueen Jan 8, 2020
f857964
factoring
xmcqueen Jan 8, 2020
4330b01
cleanup
xmcqueen Jan 8, 2020
9038a0a
docs
xmcqueen Jan 8, 2020
e32ba1d
rename and add to Makefilf
xmcqueen Jan 8, 2020
4e8ed42
Merge remote-tracking branch 'upstream/master'
xmcqueen Jan 8, 2020
5ff5b0c
Merge branch 'tool-sample'
xmcqueen Jan 8, 2020
9714424
factor flags into main per PR comment
xmcqueen Jan 9, 2020
b2af08e
many of the PR comments are done
xmcqueen Jan 9, 2020
66c577a
more PR comments
xmcqueen Jan 9, 2020
9c73f0f
last code comments, next add some tests
xmcqueen Jan 9, 2020
a70df4d
factoring
xmcqueen Jan 9, 2020
3685e07
add yaml loader test
xmcqueen Jan 10, 2020
62a7368
checkpoint refactor to redo the cli syntax
xmcqueen Jan 10, 2020
bc86828
finished putting in new cli syntax
xmcqueen Jan 11, 2020
9e7f3fb
factoring
xmcqueen Jan 11, 2020
f9981ff
renaming and README
xmcqueen Jan 11, 2020
385ddf0
working test for arg processing
xmcqueen Jan 12, 2020
024e500
added test for namespaces command line parsing
xmcqueen Jan 12, 2020
75e49d2
add placements cli args test
xmcqueen Jan 13, 2020
0e13026
cleaning up
xmcqueen Jan 13, 2020
099d24d
address more PR comments
xmcqueen Jan 13, 2020
2ef9297
checkpoint
xmcqueen Jan 28, 2020
8a6a793
better arg handling started and test passes
xmcqueen Jan 29, 2020
e7651f5
make it more test-friendly and make the test less sucky
xmcqueen Jan 30, 2020
becd223
rename some items
xmcqueen Jan 31, 2020
0fc035f
checkpoint
xmcqueen Feb 1, 2020
e77f0ba
checkpoint
xmcqueen Feb 2, 2020
51f92dd
add an operation type to the yaml and wrap the existing pb
xmcqueen Feb 2, 2020
95f239f
add an operation type to the yaml and wrap the existing pb
xmcqueen Feb 2, 2020
383f9e8
checkpoint
xmcqueen Feb 3, 2020
d2bbeb4
checkpoint
xmcqueen Feb 3, 2020
be670f1
loader is working and tests are passing
xmcqueen Feb 3, 2020
1f8bfe5
all commands work and tests pass. next add zap then cleanup
xmcqueen Feb 4, 2020
fa9dc7a
factor
xmcqueen Feb 4, 2020
f38dda5
remove the old code
xmcqueen Feb 4, 2020
f08e1c6
deleted cruft
xmcqueen Feb 4, 2020
915a5b5
cleaning up names
xmcqueen Feb 4, 2020
f6c462e
cleaning up
xmcqueen Feb 4, 2020
8258385
add zap
xmcqueen Feb 5, 2020
47d28b1
add usage messages and zap
xmcqueen Feb 5, 2020
3467e72
readme
xmcqueen Feb 5, 2020
b3384e3
readme and go fmt
xmcqueen Feb 5, 2020
7e56aae
restore a deleted tab from the Makefile
xmcqueen Feb 5, 2020
bd3be5f
make the bottom return errors too
xmcqueen Feb 5, 2020
400bfe3
fix bug in apply yaml
xmcqueen Feb 6, 2020
79a82f0
reorg and fix peeker
xmcqueen Mar 11, 2020
40b339e
probably working again with cobra now
xmcqueen Mar 16, 2020
49bb639
tested with cobra and added some aliases
xmcqueen Mar 16, 2020
ee2e442
add delete namespace
xmcqueen Mar 16, 2020
17dffdc
move output to logger per comment
xmcqueen Mar 16, 2020
b0a787f
factor out the logger instantiation
xmcqueen Mar 16, 2020
79a1090
address pr comments
xmcqueen Mar 25, 2020
e9835db
go gmt and fix statusCode check
xmcqueen Mar 25, 2020
79a6805
fix peeker test
xmcqueen Mar 26, 2020
e0caad9
fix example yamls which didnt match the tests
xmcqueen Mar 26, 2020
02a952a
clean it up a bit
xmcqueen Mar 26, 2020
fcafd11
go fmt
xmcqueen Mar 26, 2020
0a613b2
tiny cleanup
xmcqueen Mar 26, 2020
d597f51
Merge branch 'master' into master
robskillington Apr 6, 2020
0a6e318
fixed nil data case in checkForAndHandleError error log line
xmcqueen Apr 7, 2020
63969be
Merge branch 'master' into master
robskillington Apr 14, 2020
c654e44
Address feedback
robskillington Apr 14, 2020
a11e6c1
Delete unused
robskillington Apr 14, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ TOOLS := \
verify_index_files \
carbon_load \
docs_test \
m3ctl \

.PHONY: setup
setup:
Expand Down
2 changes: 1 addition & 1 deletion docs/operational_guide/placement_configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ curl -X POST localhost:7201/api/v1/services/m3db/placement/init -d '{
"endpoint": "<NODE_3_HOST_NAME>:<NODE_3_PORT>",
"hostname": "<NODE_3_HOST_NAME>",
"port": <NODE_3_PORT>
},
}
]
}'
```
Expand Down
82 changes: 82 additions & 0 deletions src/cmd/tools/m3ctl/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
M3DB CLI Tool
=============

This is a CLI tool to do some things that may be desirable for
cluster introspection, or for operational purposes.

Where configuration data is required its provided via YAML.

You can:

* create a database per the simplified database create API
* list namespaces
* delete namespaces
* list placements
* delete placements
* add nodes
* remove nodes

NOTE: This tool can delete namespaces and placements. It can be
quite hazardous if used without adequate understanding of your m3db
cluster's topology, or without a decent understanding of how m3db
works.

Examples
-------

# show help
m3ctl -h
# create a database
m3ctl apply -f ./database/examples/dbcreate.yaml
# list namespaces
m3ctl get ns
# delete a namespace
m3ctl delete ns -id default
# list placements
m3ctl get pl
# point to some remote and list namespaces
m3ctl -endpoint http://localhost:7201 get ns
# check the namespaces in a kubernetes cluster
# first setup a tunnel via kubectl port-forward ... 7201
m3ctl -endpoint http://localhost:7201 get ns
# list the ids of the placements
m3ctl -endpoint http://localhost:7201 get pl | jq .placement.instances[].id

Some example yaml files for the "apply" subcommand are provided in the yaml/examples directory.
Here's one to initialize a topology:

---
operation: init
num_shards: 64
replication_factor: 1
instances:
- id: nodeid1
isolation_group: isogroup1
zone: etcd1
weight: 100
endpoint: node1:9000
hostname: node1
port: 9000
- id: nodeid2
isolation_group: isogroup2
zone: etcd1
weight: 100
endpoint: node2:9000
hostname: node2
port: 9000
- id: nodeid3
isolation_group: isogroup3
zone: etcd1
weight: 100
endpoint: node3:9000
hostname: node3
port: 9000


See the examples directories below.

References
==========

[https://m3db.github.io/m3/operational_guide](operational guide)
[api docs](https://www.m3db.io/openapi/)
41 changes: 41 additions & 0 deletions src/cmd/tools/m3ctl/apply/apply.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) 2020 Uber Technologies, Inc.
//
// 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 apply
xmcqueen marked this conversation as resolved.
Show resolved Hide resolved

import (
"fmt"
"go.uber.org/zap"

"github.com/m3db/m3/src/cmd/tools/m3ctl/client"
"github.com/m3db/m3/src/cmd/tools/m3ctl/yaml"
)

// DoApply does the API call to handle the kubectl apply command
// It looks at the yaml, figures out what kind of API call to make
// Sends it all off to the API
func DoApply(endpoint string, filepath string, logger *zap.Logger) error {
path, data, err := yaml.Load(filepath, logger)
if err != nil {
return err
}
url := fmt.Sprintf("%s%s", endpoint, path)
return client.DoPost(url, data, client.Dumper, logger)
}
48 changes: 48 additions & 0 deletions src/cmd/tools/m3ctl/client/checker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) 2020 Uber Technologies, Inc.
//
// 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 client
xmcqueen marked this conversation as resolved.
Show resolved Hide resolved

import (
"fmt"
"io/ioutil"
"net/http"

"go.uber.org/zap"
)

func checkForAndHandleError(url string, resp *http.Response, zl *zap.Logger) error {
if resp.StatusCode/100 != 2 {
dat, _ := ioutil.ReadAll(resp.Body)
if dat != nil {
zl.Error("error response",
zap.Error(fmt.Errorf("status %d", resp.StatusCode)),
zap.String("url", url),
zap.ByteString("response", dat))
} else {
zl.Error("error response",
zap.Error(fmt.Errorf("status %d", resp.StatusCode)),
zap.String("url", url),
zap.ByteString("response", dat))
xmcqueen marked this conversation as resolved.
Show resolved Hide resolved
}
return fmt.Errorf("error from m3db status=%s, url=%s\n", resp.Status, url)
}
return nil
}
107 changes: 107 additions & 0 deletions src/cmd/tools/m3ctl/client/http.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright (c) 2020 Uber Technologies, Inc.
//
// 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 client
xmcqueen marked this conversation as resolved.
Show resolved Hide resolved

import (
"fmt"
"io"
"io/ioutil"
"net/http"
"time"

"go.uber.org/zap"
)

const timeout = time.Duration(5 * time.Second)

// DoGet is the low level call to the backend api for gets
func DoGet(url string, getter func(reader io.Reader, zl *zap.Logger) error, zl *zap.Logger) error {
zl.Info("request", zap.String("method", "get"), zap.String("url", url))
client := http.Client{
Timeout: timeout,
}
resp, err := client.Get(url)
if err != nil {
return err
}
defer func() {
ioutil.ReadAll(resp.Body)
resp.Body.Close()
}()
if err := checkForAndHandleError(url, resp, zl); err != nil {
return err
}
return getter(resp.Body, zl)
}

// DoPost is the low level call to the backend api for posts
func DoPost(url string, data io.Reader, getter func(reader io.Reader, zl *zap.Logger) error, zl *zap.Logger) error {
zl.Info("request", zap.String("method", "post"), zap.String("url", url))
client := &http.Client{
Timeout: timeout,
}
req, err := http.NewRequest(http.MethodPost, url, data)
req.Header.Add("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return err
}
defer func() {
ioutil.ReadAll(resp.Body)
resp.Body.Close()
}()
if err := checkForAndHandleError(url, resp, zl); err != nil {
return err
}
return getter(resp.Body, zl)
}

// DoDelete is the low level call to the backend api for deletes
func DoDelete(url string, getter func(reader io.Reader, zl *zap.Logger) error, zl *zap.Logger) error {
zl.Info("request", zap.String("method", "delete"), zap.String("url", url))
client := &http.Client{
Timeout: timeout,
}
req, err := http.NewRequest(http.MethodDelete, url, nil)
req.Header.Add("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return err
}
defer func() {
ioutil.ReadAll(resp.Body)
resp.Body.Close()
}()
if err := checkForAndHandleError(url, resp, zl); err != nil {
return err
}
return getter(resp.Body, zl)
}

// Dumper is a simple printer for http responses
func Dumper(in io.Reader, zl *zap.Logger) error {
dat, err := ioutil.ReadAll(in)
if err != nil {
return err
}
fmt.Println(string(dat))
return nil
}
32 changes: 32 additions & 0 deletions src/cmd/tools/m3ctl/errors/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (c) 2020 Uber Technologies, Inc.
//
// 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 errors
xmcqueen marked this conversation as resolved.
Show resolved Hide resolved

type FlagsError struct {
Message string
}

func (e *FlagsError) Error() string {
if e == nil {
return ""
}
return e.Message
}
Loading