NOTE: this project is still in an early stage
If you like this project, please checkout TODOs and open an issue if you'd like to contribute or discuss anything in particular.
> ./kubeplay
kubeplay (namespace="*")> pods # list pods in the cluster
<list-of-pods>
kubeplay (namespace="*")> @pod = _.any # pick a random pod from the list
kubeplay (namespace="*")> puts @pod.to_json # output the pod definition in JSON
{
"metadata": {
...
},
"spec": {
...
"containers": [
{
...
}
],
},
"status": {
...
}
}
kubeplay (namespace="*")> puts @pod.to_ruby # output the same as a Ruby hash
{ ... }
kubeplay (namespace="*")> @pod.delete! # I am a chaos monkey :)Currently implemented verbs are the following:
podsservicesreplicasetsdaemonsets
Each of these can be used with index operator, e.g. services[10], as well as first, last and any methonds.
Any resource object can be converted to a JSON string with to_json method, or a Ruby object with to_ruby.
With a Ruby object reprsentation you can do things like this:
@metadata = replicasets("*/").to_ruby.items.map do |k,v|
v.metadata
end
@metadata.each do |i|
puts "Name:\t#{i.name}"
puts "Labels:\t#{i.labels}"
puts
endYou can define a verb aliases with def_alias, e.g. to create an rs verb alias for replicasets use
def_alias :rs, :replicasetsBy default a verb operates on all namespaces, hence (namespace="*") is shown in the prompt.
You can switch current namespaces with namespace verb, e.g.
kubeplay (namespace="*")> namespace "kube-system"
kubeplay (namespace="kube-system")>To go back to all-namespaces mode, use namespace "*".
A verb may take up two arguments in any order - a glob string and a block or hash.
To get all replica sets in default namespaces which have label app not matching foo or bar and label version matching 0.1 or 0.2 use
replicasets "default/", labels: -> { @app !~ %w(foo bar) ; @version =~ %w(0.1 0.2) ; }To get all running pods with label app matching foo or bar use
pods { @app =~ %w(foo bar) ; status.phase == "Running" ; }Here are some examples illustrating the types of glob expressions that kubeplay understands.
Get all pods in kube-systems namespace:
pods "kube-system/"Get all pods in all namespace:
pods "*/"Get all pods in current namespace with name matching *foo*:
pods "*foo*"More specifically, this enables getting pods in a namespace other then current like this:
kubeplay (namespace="default")> pods "kube-system/foo-*"Or, gettin pods with name matching "bar-* in all namespace like this:
kubeplay (namespace="default")> pods "*/bar-*"NOTE: if current namespace is
"*",pods "*"is the same aspods;pods "*/*"is always the same aspods "*/".
Another argument a resource verb understand is a block specifying label and field selectors using special syntax outlined below.
To match a label agains a set of values, use label("name") =~ %w(foo bar), or !~.
If you want to just get resources with a certain label to set anything, use label("baz").defined?
This
{
label("name") =~ %w(foo bar)
label("baz").defined?
}will compile a selector string name in (foo, bar),myapp.
And this
{
label("name") !~ %w(foo bar)
label("baz").defined?
}will compile a selector string name notin (foo, bar),myapp.
Some well-known labels have shortuct, e.g.
{
@app !~ %w(foo bar)
@version =~ %w(0.1 0.2)
@tier =~ %w(frontend backend)
}Simply pass a block like this:
replicasets { @app !~ %w(foo bar); @version =~ %w(0.1 0.2); @tier =~ %w(frontend backend); }You can also use make_label_selector verb to construct these expressions and save those to variabels etc.
This syntax is different, yet somewhat simpler.
Here is a selector mathing all running pods:
{ status.phase != :Running }To get all running pods with label tier mathcing backend:
pods { status.phase != :Running ; @tier =~ "backend" ; }Alternatively, if you prefer to be more explicit, you can use a hash:
pods fields: -> { status.phase != :Running }, labels: -> { @tier =~ "backend" }You can also use compose selector expressions diretly as strings, if you prefer:
pods fields: "status.phase != Running", labels: "tier in (backend)"To get grep logs for any pod matching given selector
pods{ @name =~ "launch-generator" ; }.any.logs.grep ".*INFO:.*", ".*user-agent:.*"> ./kubeplay -kubeconfig ~/.kube/config
kubeplay (namespace="*")> @pod = make_pod(image: "errordeveloper/foo:latest")
kubeplay (namespace="*")> puts _.to_json
{
"metadata": {
"creationTimestamp": null,
"labels": {
"name": "foo"
}
},
"spec": {
"containers": [
{
"name": "foo",
"image": "errordeveloper/foo:latest",
"resources": {}
}
]
},
"status": {}
}
kubeplay (namespace="*")> @pod.create!
kubeplay (namespace="*")> @pod.delete!
kubeplay (namespace="*")> ^D
>Here are some TODO items and ideas.
-
pod.delete! -
pod.create! -
pod.logs&pod.logs.grep -
pods.logs&pods.logs.grep -
pod.logs.pagerandpod.logs.grep.pager - grep logs in any set of resources
- more fluent behaviour of set resources, e.g.
replicasets.podsand notreplicasets.any.pods - reverse lookup, e.g. given
@rs = replicasets.any,@rs.pods.any.ownershould be the same as@rs - way to run scripts and not just REPL
- extend resource generator functionality
-
ReplicaSet+Service -
KubefileDSL
-
- simple framework for controllers and 3rd-party resource (e.g. chaos monkey of sorts, or use terraform to create an exteranl resource and store URL in a secret, custom policy controller made easy)
- multi-cluster support
- resource diff
- network policy tester framework
- eval/exec code in a pod
- test framework for apps, e.g. "Here is my app, it has a configmap and a secrete, and I want to test if it works"
Get the source code and build the dependencies:
go get github.com/Masterminds/glide
go get -d github.com/errordeveloper/kubeplay
cd $GOPATH/src/github.com/errordeveloper/kubeplay
$GOPATH/bin/glide up -v
make -C vendor/github.com/mitchellh/go-mruby libmruby.a
go install ./rubykubeBuild kubeplay:
go build .The mruby integration was inspired by @erikh's box, and some of the code was initially copied from there.