diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000000000000000000000000000000000000..b95e22b6e88beb0d607c8828450c5a0f12d2d321
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,3 @@
+approvers:
+ - lizrice
+ - jerbia
diff --git a/cfg/config.yaml b/cfg/config.yaml
index c8c89c9b647eeae87b84207b06a20f4386b309f2..07548acd2c30bbc6b81eb30cda3d9276a8743041 100644
--- a/cfg/config.yaml
+++ b/cfg/config.yaml
@@ -29,7 +29,7 @@ installation:
       conf:
         apiserver: /etc/kubernetes/apiserver
         scheduler: /etc/kubernetes/scheduler
-        controller-manager: /etc/kubernetes/apiserver
+        controller-manager: /etc/kubernetes/controller-manager
     node:
       bin:
         kubelet: kubelet
diff --git a/cfg/master.yaml b/cfg/master.yaml
index 6f2cc33b474a2ca01eab6f6c3b652b106c9dcd38..7005f9519f20bcbfdde1330b47a9fee0b01f41cc 100644
--- a/cfg/master.yaml
+++ b/cfg/master.yaml
@@ -479,19 +479,14 @@ groups:
               parameter to \"--experimental-encryption-provider-config=</path/to/EncryptionConfig/File>\""
       scored: true
 
-# TODO: provide flag to WARN of manual tasks which we can't automate.
     - id: 1.1.35
       text: "Ensure that the encryption provider is set to aescbc (Scored)"
       audit: "ps -ef | grep $apiserverbin | grep -v grep"
-      tests:
-        test_items:
-        - flag: "requires manual intervention"
-          set: true
+      type: "manual"
       remediation: "Follow the Kubernetes documentation and configure a EncryptionConfig file. In this file,
               choose aescbc as the encryption provider"
       scored: true
 
-
 - id: 1.2
   text: "Scheduler"
   checks:
@@ -573,7 +568,13 @@ groups:
               KUBE_CONTROLLER_MANAGER_ARGS parameter to include --root-ca-file=<file>"
       scored: true
 
-# TODO: 1.3.6 is manual, provide way to WARN
+    - id: 1.3.6
+      text: "Apply Security Context to Your Pods and Containers (Not Scored)"
+      type: "manual"
+      remediation: "Edit the /etc/kubernetes/controller-manager file on the master node and set the
+              KUBE_CONTROLLER_MANAGER_ARGS parameter to a value to include 
+              \"--feature-gates=RotateKubeletServerCertificate=true\""
+      scored: false
 
     - id: 1.3.7
       text: " Ensure that the RotateKubeletServerCertificate argument is set to true (Scored)"
@@ -751,6 +752,20 @@ groups:
               chmod 700 /var/lib/etcd/default.etcd"
       scored: true
 
+    - id: 1.4.12
+      text: "Ensure that the etcd data directory ownership is set to etcd:etcd (Scored)"
+      audit: "ps -ef | grep $etcdbin | grep -v grep | grep -o data-dir=.* | cut -d= -f2 | xargs stat -c %U:%G"
+      tests:
+        test_items:
+        - flag: "etcd:etcd"
+          set: true
+      remediation: "On the etcd server node, get the etcd data directory, passed as an argument --data-dir ,
+              from the below command:\n
+                      ps -ef | grep etcd\n
+              Run the below command (based on the etcd data directory found above). For example,\n
+                      chown etcd:etcd /var/lib/etcd/default.etcd"
+      scored: true
+
 - id: 1.5
   text: "etcd"
   checks:
@@ -893,3 +908,65 @@ groups:
       remediation: "Follow the etcd documentation and create a dedicated certificate authority setup for the 
               etcd service."
       scored: false 
+
+- id: 1.6
+  text: "General Security Primitives"
+  checks:
+    - id: 1.6.1
+      text: "Ensure that the cluster-admin role is only used where required (Not Scored)"
+      type: "manual"
+      remediation: "Remove any unneeded clusterrolebindings: kubectl delete clusterrolebinding [name]"
+      scored: false
+
+    - id: 1.6.2
+      text: "Create Pod Security Policies for your cluster (Not Scored)"
+      type: "manual"
+      remediation: "Follow the documentation and create and enforce Pod Security Policies for your cluster.
+              Additionally, you could refer the \"CIS Security Benchmark for Docker\" and follow the
+              suggested Pod Security Policies for your environment."
+      scored: false
+
+    - id: 1.6.3
+      text: "Create administrative boundaries between resources using namespaces (Not Scored)"
+      type: "manual"
+      remediation: "Follow the documentation and create namespaces for objects in your deployment as you
+              need them."
+      scored: false
+
+    - id: 1.6.4
+      text: "Create network segmentation using Network Policies (Not Scored)"
+      type: "manual"
+      remediation: "Follow the documentation and create NetworkPolicy objects as you need them."
+      scored: false
+
+    - id: 1.6.5
+      text: "Ensure that the seccomp profile is set to docker/default in your pod definitions (Not Scored)"
+      type: "manual"
+      remediation: "Seccomp is an alpha feature currently. By default, all alpha features are disabled. So, you
+              would need to enable alpha features in the apiserver by passing \"--feature-
+              gates=AllAlpha=true\" argument.\n
+              Edit the $apiserverconf file on the master node and set the KUBE_API_ARGS
+              parameter to \"--feature-gates=AllAlpha=true\"
+              KUBE_API_ARGS=\"--feature-gates=AllAlpha=true\""
+      scored: false
+
+    - id: 1.6.6
+      text: "Apply Security Context to Your Pods and Containers (Not Scored)"
+      type: "manual"
+      remediation: "Follow the Kubernetes documentation and apply security contexts to your pods. For a
+              suggested list of security contexts, you may refer to the CIS Security Benchmark for Docker
+              Containers."
+      scored: false
+
+    - id: 1.6.7
+      text: "Configure Image Provenance using ImagePolicyWebhook admission controller (Not Scored)"
+      type: "manual"
+      remediation: "Follow the Kubernetes documentation and setup image provenance."
+      scored: false
+
+    - id: 1.6.8
+      text: "Configure Network policies as appropriate (Not Scored)"
+      type: "manual"
+      remediation: "Follow the Kubernetes documentation and setup network policies as appropriate."
+      scored: false
+
diff --git a/check/check.go b/check/check.go
index 86f3939a2edd55cd32b014eb454c2713766811bb..7a41b199c5c84a34993ae62b9e2291c0e2cf7e8d 100644
--- a/check/check.go
+++ b/check/check.go
@@ -18,10 +18,11 @@ import (
 	"bytes"
 	"fmt"
 	"io"
-	"os"
 	"os/exec"
 	"regexp"
 	"strings"
+
+	"github.com/golang/glog"
 )
 
 // NodeType indicates the type of node (master, node, federated).
@@ -61,6 +62,7 @@ type Check struct {
 	ID          string `yaml:"id" json:"id"`
 	Text        string
 	Audit       string      `json:"omit"`
+	Type        string      `json:"type"`
 	Commands    []*exec.Cmd `json:"omit"`
 	Tests       *tests      `json:"omit"`
 	Set         bool        `json:"omit"`
@@ -70,7 +72,13 @@ type Check struct {
 
 // Run executes the audit commands specified in a check and outputs
 // the results.
-func (c *Check) Run(verbose bool) {
+func (c *Check) Run() {
+	// If check type is manual, force result to WARN.
+	if c.Type == "manual" {
+		c.State = WARN
+		return
+	}
+
 	var out bytes.Buffer
 	var errmsgs string
 
@@ -147,9 +155,7 @@ func (c *Check) Run(verbose bool) {
 		i++
 	}
 
-	if verbose && errmsgs != "" {
-		fmt.Fprintf(os.Stderr, "%s\n", errmsgs)
-	}
+	glog.V(2).Info("%s\n", errmsgs)
 
 	res := c.Tests.execute(out.String())
 	if res {
diff --git a/check/controls.go b/check/controls.go
index 8f7530c8076b1a9330c1631583d28438c10b1bca..dfea0067178a0b1436669852993716d572104ae9 100644
--- a/check/controls.go
+++ b/check/controls.go
@@ -68,7 +68,7 @@ func NewControls(t NodeType, in []byte) (*Controls, error) {
 }
 
 // RunGroup runs all checks in a group.
-func (controls *Controls) RunGroup(verbose bool, gids ...string) Summary {
+func (controls *Controls) RunGroup(gids ...string) Summary {
 	g := []*Group{}
 	controls.Summary.Pass, controls.Summary.Fail, controls.Summary.Warn = 0, 0, 0
 
@@ -82,7 +82,7 @@ func (controls *Controls) RunGroup(verbose bool, gids ...string) Summary {
 		for _, gid := range gids {
 			if gid == group.ID {
 				for _, check := range group.Checks {
-					check.Run(verbose)
+					check.Run()
 					summarize(controls, check)
 				}
 
@@ -96,7 +96,7 @@ func (controls *Controls) RunGroup(verbose bool, gids ...string) Summary {
 }
 
 // RunChecks runs the checks with the supplied IDs.
-func (controls *Controls) RunChecks(verbose bool, ids ...string) Summary {
+func (controls *Controls) RunChecks(ids ...string) Summary {
 	g := []*Group{}
 	m := make(map[string]*Group)
 	controls.Summary.Pass, controls.Summary.Fail, controls.Summary.Warn = 0, 0, 0
@@ -110,7 +110,7 @@ func (controls *Controls) RunChecks(verbose bool, ids ...string) Summary {
 		for _, check := range group.Checks {
 			for _, id := range ids {
 				if id == check.ID {
-					check.Run(verbose)
+					check.Run()
 					summarize(controls, check)
 
 					// Check if we have already added this checks group.
diff --git a/cmd/common.go b/cmd/common.go
index ae8119de8554c1cbd2bedee83b1fe00842224431..d27dc1f9dbbdafe23f7459cd92764fa7ee37a60b 100644
--- a/cmd/common.go
+++ b/cmd/common.go
@@ -17,7 +17,6 @@ package cmd
 import (
 	"fmt"
 	"io/ioutil"
-	"os"
 	"strings"
 
 	"github.com/aquasecurity/kube-bench/check"
@@ -46,7 +45,8 @@ var (
 	errmsgs string
 
 	// TODO: Consider specifying this in config file.
-	kubeVersion = "1.7.0"
+	kubeMajorVersion = "1"
+	kubeMinorVersion = "7"
 )
 
 func runChecks(t check.NodeType) {
@@ -59,7 +59,7 @@ func runChecks(t check.NodeType) {
 	schedulerBin = viper.GetString("installation." + installation + ".master.bin.scheduler")
 	schedulerConf = viper.GetString("installation." + installation + ".master.conf.scheduler")
 	controllerManagerBin = viper.GetString("installation." + installation + ".master.bin.controller-manager")
-	controllerManagerConf = viper.GetString("installation." + installation + ".master.conf.controler-manager")
+	controllerManagerConf = viper.GetString("installation." + installation + ".master.conf.controller-manager")
 	config = viper.GetString("installation." + installation + ".config")
 
 	etcdBin = viper.GetString("etcd.bin")
@@ -78,7 +78,8 @@ func runChecks(t check.NodeType) {
 	fedControllerManagerBin = viper.GetString("installation." + installation + ".federated.bin.controller-manager")
 
 	// Run kubernetes installation validation checks.
-	warns := verifyNodeType(t)
+	verifyKubeVersion(kubeMajorVersion, kubeMinorVersion)
+	verifyNodeType(t)
 
 	switch t {
 	case check.MASTER:
@@ -91,8 +92,7 @@ func runChecks(t check.NodeType) {
 
 	in, err := ioutil.ReadFile(file)
 	if err != nil {
-		fmt.Fprintf(os.Stderr, "error opening %s controls file: %v\n", t, err)
-		os.Exit(1)
+		exitWithError(fmt.Errorf("error opening %s controls file: %v", t, err))
 	}
 
 	// Variable substitutions. Replace all occurrences of variables in controls files.
@@ -102,7 +102,6 @@ func runChecks(t check.NodeType) {
 	s = strings.Replace(s, "$schedulerconf", schedulerConf, -1)
 	s = strings.Replace(s, "$controllermanagerbin", controllerManagerBin, -1)
 	s = strings.Replace(s, "$controllermanagerconf", controllerManagerConf, -1)
-	s = strings.Replace(s, "$controllermanagerconf", controllerManagerConf, -1)
 	s = strings.Replace(s, "$config", config, -1)
 
 	s = strings.Replace(s, "$etcdbin", etcdBin, -1)
@@ -120,63 +119,47 @@ func runChecks(t check.NodeType) {
 
 	controls, err := check.NewControls(t, []byte(s))
 	if err != nil {
-		fmt.Fprintf(os.Stderr, "error setting up %s controls: %v\n", t, err)
-		os.Exit(1)
+		exitWithError(fmt.Errorf("error setting up %s controls: %v", t, err))
 	}
 
 	if groupList != "" && checkList == "" {
 		ids := cleanIDs(groupList)
-		summary = controls.RunGroup(verbose, ids...)
+		summary = controls.RunGroup(ids...)
 	} else if checkList != "" && groupList == "" {
 		ids := cleanIDs(checkList)
-		summary = controls.RunChecks(verbose, ids...)
+		summary = controls.RunChecks(ids...)
 	} else if checkList != "" && groupList != "" {
-		fmt.Fprintf(os.Stderr, "group option and check option can't be used together\n")
-		os.Exit(1)
+		exitWithError(fmt.Errorf("group option and check option can't be used together"))
 	} else {
-		summary = controls.RunGroup(verbose)
+		summary = controls.RunGroup()
 	}
 
 	// if we successfully ran some tests and it's json format, ignore the warnings
 	if (summary.Fail > 0 || summary.Warn > 0 || summary.Pass > 0) && jsonFmt {
 		out, err := controls.JSON()
 		if err != nil {
-			fmt.Fprintf(os.Stderr, "failed to output in JSON format: %v\n", err)
-			os.Exit(1)
+			exitWithError(fmt.Errorf("failed to output in JSON format: %v", err))
 		}
 
 		fmt.Println(string(out))
 	} else {
-		prettyPrint(warns, controls, summary)
+		prettyPrint(controls, summary)
 	}
 }
 
 // verifyNodeType checks the executables and config files are as expected
 // for the specified tests (master, node or federated).
-func verifyNodeType(t check.NodeType) []string {
-	var w []string
-	// Always clear out error messages.
-	errmsgs = ""
-
+func verifyNodeType(t check.NodeType) {
 	switch t {
 	case check.MASTER:
-		w = append(w, verifyBin(apiserverBin, schedulerBin, controllerManagerBin)...)
-		w = append(w, verifyConf(apiserverConf, schedulerConf, controllerManagerConf)...)
-		w = append(w, verifyKubeVersion(apiserverBin)...)
+		verifyBin(apiserverBin, schedulerBin, controllerManagerBin)
+		verifyConf(apiserverConf, schedulerConf, controllerManagerConf)
 	case check.NODE:
-		w = append(w, verifyBin(kubeletBin, proxyBin)...)
-		w = append(w, verifyConf(kubeletConf, proxyConf)...)
-		w = append(w, verifyKubeVersion(kubeletBin)...)
+		verifyBin(kubeletBin, proxyBin)
+		verifyConf(kubeletConf, proxyConf)
 	case check.FEDERATED:
-		w = append(w, verifyBin(fedApiserverBin, fedControllerManagerBin)...)
-		w = append(w, verifyKubeVersion(fedApiserverBin)...)
-	}
-
-	if verbose {
-		fmt.Fprintf(os.Stderr, "%s\n", errmsgs)
+		verifyBin(fedApiserverBin, fedControllerManagerBin)
 	}
-
-	return w
 }
 
 // colorPrint outputs the state in a specific colour, along with a message string
@@ -186,13 +169,9 @@ func colorPrint(state check.State, s string) {
 }
 
 // prettyPrint outputs the results to stdout in human-readable format
-func prettyPrint(warnings []string, r *check.Controls, summary check.Summary) {
+func prettyPrint(r *check.Controls, summary check.Summary) {
 	colorPrint(check.INFO, fmt.Sprintf("Using config file: %s\n", viper.ConfigFileUsed()))
 
-	for _, w := range warnings {
-		colorPrint(check.WARN, w)
-	}
-
 	colorPrint(check.INFO, fmt.Sprintf("%s %s\n", r.ID, r.Text))
 	for _, g := range r.Groups {
 		colorPrint(check.INFO, fmt.Sprintf("%s %s\n", g.ID, g.Text))
diff --git a/cmd/root.go b/cmd/root.go
index 5429c2c5649e6839de8718fe7309285c42293edc..aed8b422c030a4a7e26d322993b63e3e30087c95 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -15,6 +15,7 @@
 package cmd
 
 import (
+	goflag "flag"
 	"fmt"
 	"os"
 
@@ -34,11 +35,12 @@ var (
 	nodeFile      string
 	federatedFile string
 
+	loud bool
+
 	kubeConfDir     string
 	etcdConfDir     string
 	flanneldConfDir string
 
-	verbose      bool
 	installation string
 )
 
@@ -52,6 +54,9 @@ var RootCmd = &cobra.Command{
 // Execute adds all child commands to the root command sets flags appropriately.
 // This is called by main.main(). It only needs to happen once to the rootCmd.
 func Execute() {
+	goflag.Set("logtostderr", "true")
+	goflag.CommandLine.Parse([]string{})
+
 	if err := RootCmd.Execute(); err != nil {
 		fmt.Println(err)
 		os.Exit(-1)
@@ -83,7 +88,11 @@ func init() {
 		`Run all the checks under this comma-delimited list of groups. Example --group="1.1"`,
 	)
 	RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is ./cfg/config.yaml)")
-	RootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output (default false)")
+
+	goflag.CommandLine.VisitAll(func(goflag *goflag.Flag) {
+		RootCmd.PersistentFlags().AddGoFlag(goflag)
+	})
+
 }
 
 // initConfig reads in config file and ENV variables if set.
@@ -103,5 +112,4 @@ func initConfig() {
 		colorPrint(check.FAIL, fmt.Sprintf("Failed to read config file: %v\n", err))
 		os.Exit(1)
 	}
-
 }
diff --git a/cmd/util.go b/cmd/util.go
index 6a1f790bff214db46c15c2ac33bb2afe0f71ff86..937e3e0f18c9c24842459854beba482e36908b14 100644
--- a/cmd/util.go
+++ b/cmd/util.go
@@ -4,10 +4,12 @@ import (
 	"fmt"
 	"os"
 	"os/exec"
+	"regexp"
 	"strings"
 
 	"github.com/aquasecurity/kube-bench/check"
 	"github.com/fatih/color"
+	"github.com/golang/glog"
 )
 
 var (
@@ -20,11 +22,35 @@ var (
 	}
 )
 
-func handleError(err error, context string) (errmsg string) {
+func printlnWarn(msg string) {
+	fmt.Fprintf(os.Stderr, "[%s] %s\n",
+		colors[check.WARN].Sprintf("%s", check.WARN),
+		msg,
+	)
+}
+
+func sprintlnWarn(msg string) string {
+	return fmt.Sprintf("[%s] %s",
+		colors[check.WARN].Sprintf("%s", check.WARN),
+		msg,
+	)
+}
+
+func exitWithError(err error) {
+	fmt.Fprintf(os.Stderr, "\n%v\n", err)
+	os.Exit(1)
+}
+
+func continueWithError(err error, msg string) string {
 	if err != nil {
-		errmsg = fmt.Sprintf("%s, error: %s\n", context, err)
+		glog.V(1).Info(err)
 	}
-	return
+
+	if msg != "" {
+		fmt.Fprintf(os.Stderr, "%s\n", msg)
+	}
+
+	return ""
 }
 
 func cleanIDs(list string) []string {
@@ -38,76 +64,121 @@ func cleanIDs(list string) []string {
 	return ids
 }
 
-func verifyConf(confPath ...string) []string {
-	var w []string
+func verifyConf(confPath ...string) {
+	var missing string
+
 	for _, c := range confPath {
 		if _, err := os.Stat(c); err != nil && os.IsNotExist(err) {
-			w = append(w, fmt.Sprintf("config file %s does not exist\n", c))
+			continueWithError(err, "")
+			missing += c + ", "
 		}
 	}
 
-	return w
+	if len(missing) > 0 {
+		missing = strings.Trim(missing, ", ")
+		printlnWarn(fmt.Sprintf("Missing kubernetes config files: %s", missing))
+	}
+
 }
 
-func verifyBin(binPath ...string) []string {
-	var w []string
-	var binList string
+func verifyBin(binPath ...string) {
+	var binSlice []string
+	var bin string
+	var missing string
+	var notRunning string
 
 	// Construct proc name for ps(1)
 	for _, b := range binPath {
-		binList += b + ","
 		_, err := exec.LookPath(b)
-		errmsgs += handleError(
-			err,
-			fmt.Sprintf("%s: command not found in path", b),
-		)
+		bin = bin + "," + b
+		binSlice = append(binSlice, b)
+		if err != nil {
+			missing += b + ", "
+			continueWithError(err, "")
+		}
 	}
+	bin = strings.Trim(bin, ",")
 
-	binList = strings.Trim(binList, ",")
-
-	// Run ps command
-	cmd := exec.Command("ps", "-C", binList, "-o", "cmd", "--no-headers")
+	cmd := exec.Command("ps", "-C", bin, "-o", "cmd", "--no-headers")
 	out, err := cmd.Output()
-	errmsgs += handleError(
-		err,
-		fmt.Sprintf("failed to run: %s", cmd.Args),
-	)
+	if err != nil {
+		continueWithError(fmt.Errorf("%s: %s", cmd.Args, err), "")
+	}
 
-	// Actual verification
-	for _, b := range binPath {
+	for _, b := range binSlice {
 		matched := strings.Contains(string(out), b)
 
 		if !matched {
-			w = append(w, fmt.Sprintf("%s is not running\n", b))
+			notRunning += b + ", "
 		}
 	}
 
-	return w
+	if len(missing) > 0 {
+		missing = strings.Trim(missing, ", ")
+		printlnWarn(fmt.Sprintf("Missing kubernetes binaries: %s", missing))
+	}
+
+	if len(notRunning) > 0 {
+		notRunning = strings.Trim(notRunning, ", ")
+		printlnWarn(fmt.Sprintf("Kubernetes binaries not running: %s", notRunning))
+	}
 }
 
-func verifyKubeVersion(b string) []string {
+func verifyKubeVersion(major string, minor string) {
 	// These executables might not be on the user's path.
-	// TODO! Check the version number using kubectl, which is more likely to be on the path.
-	var w []string
 
-	_, err := exec.LookPath(b)
-	errmsgs += handleError(
-		err,
-		fmt.Sprintf("%s: command not found on path - version check skipped", b),
-	)
+	_, err := exec.LookPath("kubectl")
+	if err != nil {
+		continueWithError(err, sprintlnWarn("Kubernetes version check skipped"))
+		return
+	}
 
-	// Check version
-	cmd := exec.Command(b, "--version")
+	cmd := exec.Command("kubectl", "version")
 	out, err := cmd.Output()
-	errmsgs += handleError(
-		err,
-		fmt.Sprintf("failed to run:%s", cmd.Args),
-	)
+	if err != nil {
+		s := fmt.Sprintf("Kubernetes version check skipped with error %v", err)
+		continueWithError(err, sprintlnWarn(s))
+		return
+	}
+
+	msg := checkVersion("Client", string(out), major, minor)
+	if msg != "" {
+		continueWithError(fmt.Errorf(msg), msg)
+	}
 
-	matched := strings.Contains(string(out), kubeVersion)
-	if !matched {
-		w = append(w, fmt.Sprintf("%s unsupported version\n", b))
+	msg = checkVersion("Server", string(out), major, minor)
+	if msg != "" {
+		continueWithError(fmt.Errorf(msg), msg)
 	}
+}
+
+var regexVersionMajor = regexp.MustCompile("Major:\"([0-9]+)\"")
+var regexVersionMinor = regexp.MustCompile("Minor:\"([0-9]+)\"")
 
-	return w
+func checkVersion(x string, s string, expMajor string, expMinor string) string {
+	regexVersion, err := regexp.Compile(x + " Version: version.Info{(.*)}")
+	if err != nil {
+		return fmt.Sprintf("Error checking Kubernetes version: %v", err)
+	}
+
+	ss := regexVersion.FindString(s)
+	major := versionMatch(regexVersionMajor, ss)
+	minor := versionMatch(regexVersionMinor, ss)
+	if major == "" || minor == "" {
+		return fmt.Sprintf("Couldn't find %s version from kubectl output '%s'", x, s)
+	}
+
+	if major != expMajor || minor != expMinor {
+		return fmt.Sprintf("Unexpected %s version %s.%s", x, major, minor)
+	}
+
+	return ""
+}
+
+func versionMatch(r *regexp.Regexp, s string) string {
+	match := r.FindStringSubmatch(s)
+	if len(match) < 2 {
+		return ""
+	}
+	return match[1]
 }
diff --git a/cmd/util_test.go b/cmd/util_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..74d955f780332758d4811af6349afa7cb249a01c
--- /dev/null
+++ b/cmd/util_test.go
@@ -0,0 +1,77 @@
+// Copyright © 2017 Aqua Security Software Ltd. <info@aquasec.com>
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cmd
+
+import (
+	"regexp"
+	"testing"
+)
+
+func TestCheckVersion(t *testing.T) {
+	kubeoutput := `Client Version: version.Info{Major:"1", Minor:"7", GitVersion:"v1.7.0", GitCommit:"d3ada0119e776222f11ec7945e6d860061339aad", GitTreeState:"clean", BuildDate:"2017-06-30T09:51:01Z", GoVersion:"go1.8.3", Compiler:"gc", Platform:"darwin/amd64"}
+	Server Version: version.Info{Major:"1", Minor:"7", GitVersion:"v1.7.0", GitCommit:"d3ada0119e776222f11ec7945e6d860061339aad", GitTreeState:"clean", BuildDate:"2017-07-26T00:12:31Z", GoVersion:"go1.8.3", Compiler:"gc", Platform:"linux/amd64"}`
+	cases := []struct {
+		t     string
+		s     string
+		major string
+		minor string
+		exp   string
+	}{
+		{t: "Client", s: kubeoutput, major: "1", minor: "7"},
+		{t: "Server", s: kubeoutput, major: "1", minor: "7"},
+		{t: "Client", s: kubeoutput, major: "1", minor: "6", exp: "Unexpected Client version 1.7"},
+		{t: "Client", s: kubeoutput, major: "2", minor: "0", exp: "Unexpected Client version 1.7"},
+		{t: "Server", s: "something unexpected", major: "2", minor: "0", exp: "Couldn't find Server version from kubectl output 'something unexpected'"},
+	}
+
+	for _, c := range cases {
+		t.Run("", func(t *testing.T) {
+			m := checkVersion(c.t, c.s, c.major, c.minor)
+			if m != c.exp {
+				t.Fatalf("Got: %s, expected: %s", m, c.exp)
+			}
+		})
+	}
+
+}
+
+func TestVersionMatch(t *testing.T) {
+	minor := regexVersionMinor
+	major := regexVersionMajor
+	client := `Client Version: version.Info{Major:"1", Minor:"7", GitVersion:"v1.7.0", GitCommit:"d3ada0119e776222f11ec7945e6d860061339aad", GitTreeState:"clean", BuildDate:"2017-06-30T09:51:01Z", GoVersion:"go1.8.3", Compiler:"gc", Platform:"darwin/amd64"}`
+	server := `Server Version: version.Info{Major:"1", Minor:"7", GitVersion:"v1.7.0", GitCommit:"d3ada0119e776222f11ec7945e6d860061339aad", GitTreeState:"clean", BuildDate:"2017-07-26T00:12:31Z", GoVersion:"go1.8.3", Compiler:"gc", Platform:"linux/amd64"}`
+
+	cases := []struct {
+		r   *regexp.Regexp
+		s   string
+		exp string
+	}{
+		{r: major, s: server, exp: "1"},
+		{r: minor, s: server, exp: "7"},
+		{r: major, s: client, exp: "1"},
+		{r: minor, s: client, exp: "7"},
+		{r: major, s: "Some unexpected string"},
+		{r: minor}, // Checking that we don't fall over if the string is empty
+	}
+
+	for _, c := range cases {
+		t.Run("", func(t *testing.T) {
+			m := versionMatch(c.r, c.s)
+			if m != c.exp {
+				t.Fatalf("Got %s expected %s", m, c.exp)
+			}
+		})
+	}
+}