diff --git a/README.md b/README.md
index 8772df6..af66ee6 100644
--- a/README.md
+++ b/README.md
@@ -5,23 +5,31 @@ Currently, this only generates a diagram similar to https://github.com/kubernete
For examples of the generated diagrams, see [Examples](#examples) below.
## Implementations
-There are two implementations, bash script version and go version. Bash script version is just a wrapper to run go version inside container.
+
+There are two implementations, bash script version and go version. Bash script version is just a wrapper to run go version inside a Docker container.
## Prerequisites
+
### Bash script version
+
`k8sviz.sh` requires:
+
- bash
- getopt
- docker
To build a container image (optional), it requires:
+
- make
### Go version
+
`k8sviz` requires:
+
- dot (graphviz) command
To build binary, it requires:
+
- make
- go
@@ -33,33 +41,45 @@ To build binary, it requires:
| k8sviz 0.3.3 or later | No | Yes |
## Installation
+
### Bash script version
+
Just download `k8sviz.sh` file and add execute permission.
+
```shell
-$ curl -LO https://raw.githubusercontent.com/mkimuram/k8sviz/master/k8sviz.sh
-$ chmod u+x k8sviz.sh
+curl -LO https://raw.githubusercontent.com/mkimuram/k8sviz/master/k8sviz.sh
+chmod u+x k8sviz.sh
```
### Go version
+
Build the binary with below commands:
+
```shell
-$ git clone https://github.com/mkimuram/k8sviz.git
-$ cd k8sviz
-$ make build
+git clone https://github.com/mkimuram/k8sviz.git
+cd k8sviz
+make build
```
-`icons` directory needs to be in the same directory to the k8sviz binary.
+By default, the `icons` directory is expected to be in the same directory as the `k8sviz` binary.
So, move them to the proper directory (Replace `PATH_TO_INSTALL` as you like).
+
```shell
-$ PATH_TO_INSTALL=$HOME/bin
-$ cp bin/k8sviz ${PATH_TO_INSTALL}
-$ cp -r icons ${PATH_TO_INSTALL}
+PATH_TO_INSTALL=$HOME/bin
+cp bin/k8sviz ${PATH_TO_INSTALL}
+cp -r icons ${PATH_TO_INSTALL}
```
+In case you wish to not put them in the same directory, you can run `k8sviz` with the command line flag `--icons` to pass the path to the directory containing the required icons.
+The path can either be relative to the binary (e.g. `../share/icons`) or absolute (e.g. `/usr/share/k8sviz/icons`).
+
## Usage
+
### Bash script version
+
```shell
-$ ./k8sviz.sh --help
+> ./k8sviz.sh --help
+
USAGE: ./k8sviz.sh [flags] args
flags:
-n,--namespace: The namespace to visualize. (default: 'default')
@@ -72,72 +92,90 @@ flags:
- ⚠️ WARNING
- If you are using Mac, only short options can be used.
- If you would like to use long options, you can install gnu-getopt and enable it by defining
- `FLAGS_GETOPT_CMD` environment variable.
- ```shell
- $ brew install gnu-getopt
- $ export FLAGS_GETOPT_CMD=/usr/local/opt/gnu-getopt/bin/getopt
- $ ./k8sviz.sh -h
- ```
+ If you are using Mac, only short options can be used.
+ If you would like to use long options, you can install gnu-getopt and enable it by defining
+ `FLAGS_GETOPT_CMD` environment variable.
+
+ ```shell
+ brew install gnu-getopt
+ export FLAGS_GETOPT_CMD=/usr/local/opt/gnu-getopt/bin/getopt
+ ./k8sviz.sh -h
+ ```
- 📝NOTE
- If you can't pull the container image or need to build it by yourself,
- you can do it by `make image-build`. It would be helpful if you specify
- `DEVEL_IMAGE` and `DEVEL_TAG` to make the image name the same to the
- default one (Below example will set image name like `mkimuram/k8sviz:0.3.4`).
- ```shell
- $ DEVEL_IMAGE=mkimuram/k8sviz DEVEL_TAG=$(cat version.txt) make image-build
- ```
-
- An example use case of creating custom image is to include AWS SDK or Google Cloud SDK.
- To create a custom image that include AWS SDK, run below command:
- ```shell
- $ DEVEL_IMAGE=mkimuram/k8sviz DEVEL_TAG=$(cat version.txt) TARGET=aws make image-build
- ```
- To create a custom image that include Google Cloud SDK, run below command:
- ```shell
- $ DEVEL_IMAGE=mkimuram/k8sviz DEVEL_TAG=$(cat version.txt) TARGET=gcloud make image-build
- ```
+ If you can't pull the container image or need to build it by yourself,
+ you can do it by `make image-build`. It would be helpful if you specify
+ `DEVEL_IMAGE` and `DEVEL_TAG` to make the image name the same to the
+ default one (Below example will set image name like `mkimuram/k8sviz:0.3.4`).
+
+ ```shell
+ DEVEL_IMAGE=mkimuram/k8sviz DEVEL_TAG=$(cat version.txt) make image-build
+ ```
+
+ An example use case of creating custom image is to include AWS SDK or Google Cloud SDK.
+ To create a custom image that include AWS SDK, run below command:
+
+ ```shell
+ DEVEL_IMAGE=mkimuram/k8sviz DEVEL_TAG=$(cat version.txt) TARGET=aws make image-build
+ ```
+
+ To create a custom image that include Google Cloud SDK, run below command:
+
+ ```shell
+ DEVEL_IMAGE=mkimuram/k8sviz DEVEL_TAG=$(cat version.txt) TARGET=gcloud make image-build
+ ```
### Go version
+
```shell
-$ ./k8sviz -h
+> ./k8sviz -h
+
Usage of ./k8sviz:
+ -i string
+ path of directory containing icons (shorthand) (default "icons")
+ -icons string
+ path of directory containing icons (default "icons")
-kubeconfig string
- absolute path to the kubeconfig file (default "/home/user1/.kube/config")
+ absolute path to the kubeconfig file (default "/home/mathym/.kube/config")
-n string
- namespace to visualize (shorthand) (default "default")
+ namespace to visualize (shorthand) (default "default")
-namespace string
- namespace to visualize (default "default")
+ namespace to visualize (default "default")
-o string
- output filename (shorthand) (default "k8sviz.out")
+ output filename (shorthand) (default "k8sviz.out")
-outfile string
- output filename (default "k8sviz.out")
+ output filename (default "k8sviz.out")
-t string
- type of output (shorthand) (default "dot")
+ type of output (shorthand) (default "dot")
-type string
- type of output (default "dot")
+ type of output (default "dot")
```
## Examples
+
Examples are only shown for old bash script version, but current go version should work in the same way.
### Examples for tutorial deployments in default namespace
+
- Generate dot file for namespace `default`
- ```shell
- ./k8sviz.sh -n default -o default.dot
- ```
+
+ ```shell
+ ./k8sviz.sh -n default -o default.dot
+ ```
+
- Generate png file for namespace `default`
- ```shell
- $ ./k8sviz.sh -n default -t png -o default.png
- ```
+
+ ```shell
+ ./k8sviz.sh -n default -t png -o default.png
+ ```
+
- Output for [an example wordpress deployment](https://kubernetes.io/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/) will be like below:
- [default.dot](./examples/wordpress/default.dot)
- [default.png](./examples/wordpress/default.png):
+
- Output for [an example cassandra deployment with statefulset](https://kubernetes.io/docs/tutorials/stateful-application/cassandra/) will be like below:
- [default.dot](./examples/cassandra/default.dot)
- [default.png](./examples/cassandra/default.png):
@@ -145,16 +183,21 @@ Examples are only shown for old bash script version, but current go version shou
### Examples for more complex deployment ([kubeflow](https://www.kubeflow.org/docs/started/k8s/kfctl-k8s-istio/) case)
+
- Generate dot file for namespace `kubeflow` and `istio-system`
- ```shell
- $ ./k8sviz.sh -n kubeflow -o examples/kubeflow/kubeflow.dot
- $ ./k8sviz.sh -n istio-system -o examples/kubeflow/istio-system.dot
- ```
+
+ ```shell
+ ./k8sviz.sh -n kubeflow -o examples/kubeflow/kubeflow.dot
+ ./k8sviz.sh -n istio-system -o examples/kubeflow/istio-system.dot
+ ```
+
- Generate png file for namespace `kubeflow` and `istio-system`
- ```shell
- $ ./k8sviz.sh -n kubeflow -t png -o examples/kubeflow/kubeflow.png
- $ ./k8sviz.sh -n istio-system -t png -o examples/kubeflow/istio-system.png
- ```
+
+ ```shell
+ ./k8sviz.sh -n kubeflow -t png -o examples/kubeflow/kubeflow.png
+ ./k8sviz.sh -n istio-system -t png -o examples/kubeflow/istio-system.png
+ ```
+
- Output:
- [kubeflow.dot](./examples/kubeflow/kubeflow.dot)
- [istio-system.dot](./examples/kubeflow/istio-system.dot)
@@ -167,4 +210,5 @@ Examples are only shown for old bash script version, but current go version shou
## License
+
This project is licensed under the Apache License - see the [LICENSE file](./LICENSE) for details
diff --git a/cmd/k8sviz/main.go b/cmd/k8sviz/main.go
index de62d60..ce889df 100644
--- a/cmd/k8sviz/main.go
+++ b/cmd/k8sviz/main.go
@@ -24,19 +24,23 @@ const (
defaultNamespace = "default"
defaultOutFile = "k8sviz.out"
defaultOutType = "dot"
+ defaultIconsDir = "icons"
descNamespaceOpt = "namespace to visualize"
descOutFileOpt = "output filename"
descOutTypeOpt = "type of output"
+ descIconsDirOpt = "path of directory containing icons"
descShortOptSuffix = " (shorthand)"
)
var (
clientset *kubernetes.Clientset
dir string
+ iconsPath string
// Flags
namespace string
outFile string
outType string
+ iconsDir string
)
func init() {
@@ -55,6 +59,8 @@ func init() {
flag.StringVar(&outFile, "o", defaultOutFile, descOutFileOpt+descShortOptSuffix)
flag.StringVar(&outType, "type", defaultOutType, descOutTypeOpt)
flag.StringVar(&outType, "t", defaultOutType, descOutTypeOpt+descShortOptSuffix)
+ flag.StringVar(&iconsDir, "icons", defaultIconsDir, descIconsDirOpt)
+ flag.StringVar(&iconsDir, "i", defaultIconsDir, descIconsDirOpt+descShortOptSuffix)
flag.Parse()
// use the current context in kubeconfig
@@ -83,6 +89,12 @@ func init() {
fmt.Fprintf(os.Stderr, "Failed to find the directory of this command: %v\n", err)
os.Exit(1)
}
+
+ if filepath.IsAbs(iconsDir) {
+ iconsPath = iconsDir
+ } else {
+ iconsPath = filepath.Join(dir, iconsDir)
+ }
}
func main() {
@@ -97,7 +109,14 @@ func main() {
os.Exit(1)
}
- g := graph.NewGraph(res, dir)
+ if _, err := os.Stat(iconsPath); err != nil {
+ if os.IsNotExist(err) {
+ fmt.Fprintf(os.Stderr, "Icons cannot be found at path: %v\n", err)
+ os.Exit(1)
+ }
+ }
+
+ g := graph.NewGraph(res, dir, iconsPath)
if outType == "dot" {
if err := g.WriteDotFile(outFile); err != nil {
diff --git a/k8sviz.sh b/k8sviz.sh
index 014d28d..44f6877 100755
--- a/k8sviz.sh
+++ b/k8sviz.sh
@@ -1,4 +1,4 @@
-#! /bin/bash
+#!/usr/bin/env bash
#### Variables ####
NAMESPACE="default"
diff --git a/pkg/graph/graph.go b/pkg/graph/graph.go
index 2507277..1d8aab6 100644
--- a/pkg/graph/graph.go
+++ b/pkg/graph/graph.go
@@ -17,14 +17,15 @@ import (
// Graph represents a graph of k8s resources
type Graph struct {
- dir string
- res *resources.Resources
- gviz *gographviz.Graph
+ dir string
+ iconsPath string
+ res *resources.Resources
+ gviz *gographviz.Graph
}
// NewGraph returns a Graph of k8s resources
-func NewGraph(res *resources.Resources, dir string) *Graph {
- g := &Graph{res: res, dir: dir, gviz: gographviz.NewGraph()}
+func NewGraph(res *resources.Resources, dir, iconsPath string) *Graph {
+ g := &Graph{res: res, dir: dir, iconsPath: iconsPath, gviz: gographviz.NewGraph()}
g.generate()
return g
diff --git a/pkg/graph/graph_test.go b/pkg/graph/graph_test.go
index 45aad8d..288b5d1 100644
--- a/pkg/graph/graph_test.go
+++ b/pkg/graph/graph_test.go
@@ -24,6 +24,7 @@ import (
var (
testns = "testns"
dir = "/testdir"
+ iconsPath = "/testdir/icons"
goldenDir = "testdata"
goldenSuffix = ".golden"
// if -update flag is specified on test run, golden file for the test will be updated
@@ -121,7 +122,7 @@ var (
OwnerReferences: []metav1.OwnerReference{{APIVersion: "batch/v1", Kind: "Job", Name: "job1"}}}},
&appsv1.DaemonSet{ObjectMeta: metav1.ObjectMeta{Namespace: testns, Name: "ds1"}},
&batchv1.Job{ObjectMeta: metav1.ObjectMeta{Namespace: testns, Name: "job1",
- OwnerReferences: []metav1.OwnerReference{{APIVersion: "batch/v1beta1", Kind: "cronJob", Name: "cronjob1"}}}},
+ OwnerReferences: []metav1.OwnerReference{{APIVersion: "batch/v1beta1", Kind: "CronJob", Name: "cronjob1"}}}},
&batchv1.CronJob{ObjectMeta: metav1.ObjectMeta{Namespace: testns, Name: "cronjob1"}},
}
)
@@ -132,8 +133,7 @@ func prepTestGraph(t *testing.T, objs ...runtime.Object) *Graph {
if err != nil {
t.Fatalf("NewResources failed: %v", err)
}
-
- return NewGraph(res, dir)
+ return NewGraph(res, dir, iconsPath)
}
func getGoldenFilePath(name string) string {
diff --git a/pkg/graph/graph_utils.go b/pkg/graph/graph_utils.go
index 06ebc99..e13a894 100644
--- a/pkg/graph/graph_utils.go
+++ b/pkg/graph/graph_utils.go
@@ -10,22 +10,24 @@ import (
)
// imagePath returns the path to the image file
-// path is {dir}/icons/{resource}-128.png
+// path is {dir}/{iconsDir}/{resource}-128.png
// ex) /icons/pod-128.png
func (g *Graph) imagePath(kind string) string {
- return filepath.Join(g.dir, "icons", kind+imageSuffix)
+ return filepath.Join(g.iconsPath, kind+imageSuffix)
}
// clusterLabel returns the resource label for namespace
// ex)
-// <
|
my-namespace |
>
+//
+// < |
my-namespace |
>
func (g *Graph) clusterLabel() string {
return g.resourceLabel("ns", g.res.Namespace)
}
// resourceLabel returns the resource label for a resource
// ex)
-// < |
my-pod |
>
+//
+// < |
my-pod |
>
func (g *Graph) resourceLabel(kind, name string) string {
return fmt.Sprintf("< |
%s |
>", g.imagePath(kind), name)
}
diff --git a/test/e2e/e2e.sh b/test/e2e/e2e.sh
index 75fe862..8790ed1 100755
--- a/test/e2e/e2e.sh
+++ b/test/e2e/e2e.sh
@@ -1,4 +1,4 @@
-#! /bin/bash
+#!/usr/bin/env bash
KEEP_RESULT="${KEEP_RESULT:-false}"
@@ -74,7 +74,7 @@ function create_cluster() {
curl -Lo ${TEST_KIND_BIN} https://kind.sigs.k8s.io/dl/v0.10.0/kind-linux-amd64
chmod +x ${TEST_KIND_BIN}
- # Change path for kubeconfig
+ # Change path for kubeconfig
export KUBECONFIG=${TEST_KUBECONFIG_PATH}
# Create cluster
@@ -91,7 +91,7 @@ function prepare_all() {
}
function delete_cluster() {
- # Change path for kubeconfig
+ # Change path for kubeconfig
export KUBECONFIG=${TEST_KUBECONFIG_PATH}
# Delete cluster