Skip to content

Commit

Permalink
anchor CRD interface uplift (#10)
Browse files Browse the repository at this point in the history
* anchor CRD interface uplift

* change dockerfile

* remove cp line

* rename trussio to covarity

change dockerfile

remove cp line

rename trussio to covarity

add support for manifest, PostStart, PreStop and objectRef

redo logging, add table format results

remove old test files
  • Loading branch information
spacetj committed Dec 8, 2019
1 parent d08fecc commit 3da02ef
Show file tree
Hide file tree
Showing 14 changed files with 481 additions and 53 deletions.
Binary file added anchorctl
Binary file not shown.
1 change: 1 addition & 0 deletions cmd/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,5 @@ func testExecute(cmd *cobra.Command, args []string) {
}
log.Info("kind", "kubetest", "Finished Tests")
}

}
37 changes: 28 additions & 9 deletions pkg/kubetest/assertions.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package kubetest

import (
"bytes"
"fmt"

"k8s.io/client-go/util/jsonpath"
)

func (aj *jsonTest) test(ref objectRef) (bool, error) {
func (aj *jsonTest) test(res resource) (bool, error) {

obj, err := getObject(aj.client, &ref)
obj, err := res.ObjectRef.getObject(aj.client)
if err != nil {
return false, err
}
Expand Down Expand Up @@ -41,37 +43,54 @@ func assertJSONPath(obj interface{}, path, value string) (bool, error) {
"jsonpath": path,
"expected": value,
"got": buf.String(),
"status": "FAILED",
}, "Failed asserting jsonpath on obj")
passed = false
break
}
buf.Reset()
}
log.InfoWithFields(map[string]interface{}{
"test": "AssertJSONPath",
"path": path,
"status": "PASSED",
}, "JSON Path matches expected value.")

return passed, err

}

func (av *validationTest) test(ref objectRef) (bool, error) {
_, _, err := applyAction(av.client, ref.Spec.Path, ref.Spec.Action)
func (av *validationTest) test(res resource) (bool, error) {

_, _, err := res.Manifest.apply(av.client)
if err != nil && err.Error() == av.ExpectedError {
log.Info("Expected", av.ExpectedError, "AssertValidation Passed")
log.InfoWithFields(map[string]interface{}{
"test": "AssertValidation",
"expectedError": av.ExpectedError,
"status": "PASSED",
}, "AssertValidation throws the expected error.")
return true, nil
}

log.WarnWithFields(map[string]interface{}{
"test": "AssertValidation",
"expected": av.ExpectedError,
"got": err.Error(),
"got": "Error: " + err.Error(),
"status": "FAILED",
}, "AssertValidation Failed")

return false, nil

}

func (am *mutationTest) test(ref objectRef) (bool, error) {
_, obj, err := applyAction(am.client, ref.Spec.Path, ref.Spec.Action)
func (am *mutationTest) test(res resource) (bool, error) {

if valid := res.Manifest.valid(); valid != true {
return false, fmt.Errorf("Invalid Manifest to apply")
}

_, obj, err := res.Manifest.apply(am.client)
if err != nil {
log.Warn("Error", err.Error(), "AssertMutation Failed")
return false, err
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package kubetest

import (
"io/ioutil"
"reflect"

"gopkg.in/yaml.v2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)

// getKubeClientSet returns a kubernetes client set which can be used to connect to kubernetes cluster
func getKubeClient(incluster bool, filepath string) (*kubernetes.Clientset, error) {

var config *rest.Config
var clientset *kubernetes.Clientset
var err error

if incluster == true {
config, err = rest.InClusterConfig()
} else {
config, err = clientcmd.BuildConfigFromFlags("", filepath)
}

if err != nil {
return nil, err
}

clientset, err = kubernetes.NewForConfig(config)

if err != nil {
return nil, err
}

return clientset, nil
}

func decodeTestFile(client *kubernetes.Clientset, filePath string) (*kubeTest, error) {
kubeTest := &kubeTest{}

data, err := ioutil.ReadFile(filePath)
if err != nil {
return nil, err
}

err = yaml.Unmarshal(data, &kubeTest)
if err != nil {
return nil, err
}

return kubeTest, nil
}

func getListOptions(key, value string) *metav1.ListOptions {
return &metav1.ListOptions{LabelSelector: key + "=" + value}
}

func getSlice(t interface{}) []interface{} {
var slicedInterface []interface{}

switch reflect.TypeOf(t).Kind() {
case reflect.Slice:
s := reflect.ValueOf(t)

for i := 0; i < s.Len(); i++ {
slicedInterface = append(slicedInterface, s.Index(i).Interface())
}

default:
slicedInterface = append(slicedInterface, t)
}

return slicedInterface
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package kubetest

import (
"io/ioutil"
"reflect"

"gopkg.in/yaml.v2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)

// getKubeClientSet returns a kubernetes client set which can be used to connect to kubernetes cluster
func getKubeClient(incluster bool, filepath string) (*kubernetes.Clientset, error) {

var config *rest.Config
var clientset *kubernetes.Clientset
var err error

if incluster == true {
config, err = rest.InClusterConfig()
} else {
config, err = clientcmd.BuildConfigFromFlags("", filepath)
}

if err != nil {
return nil, err
}

clientset, err = kubernetes.NewForConfig(config)

if err != nil {
return nil, err
}

return clientset, nil
}

func decodeTestFile(client *kubernetes.Clientset, filePath string) (*kubeTest, error) {
kubeTest := &kubeTest{}

data, err := ioutil.ReadFile(filePath)
if err != nil {
return nil, err
}

err = yaml.Unmarshal(data, &kubeTest)
if err != nil {
return nil, err
}

return kubeTest, nil
}

func getListOptions(key, value string) *metav1.ListOptions {
return &metav1.ListOptions{LabelSelector: key + "=" + value}
}

func getSlice(t interface{}) []interface{} {
var slicedInterface []interface{}

switch reflect.TypeOf(t).Kind() {
case reflect.Slice:
s := reflect.ValueOf(t)

for i := 0; i < s.Len(); i++ {
slicedInterface = append(slicedInterface, s.Index(i).Interface())
}

default:
slicedInterface = append(slicedInterface, t)
}

return slicedInterface
}
14 changes: 13 additions & 1 deletion pkg/kubetest/configmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ func getConfigMap(client *kubernetes.Clientset, name, namespace string) ([]v1.Co
}

func listConfigMaps(client *kubernetes.Clientset, namespace string, listOptions *metav1.ListOptions) ([]v1.ConfigMap, error) {

log.InfoWithFields(map[string]interface{}{
"kind": "Configmaps",
"Namespace": namespace,
"labelkey": listOptions.LabelSelector,
}, "Retriving object")

configmaps, err := client.CoreV1().ConfigMaps(namespace).List(*listOptions)
return configmaps.Items, err
if err != nil {
log.Error(err, "Unable to retrieve object")
return nil, err
}

return configmaps.Items, nil
}
5 changes: 4 additions & 1 deletion pkg/kubetest/kubetest.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,14 @@ func Assert(logger *logging.Logger, threshold float64, incluster bool, kubeconfi
log.Fatal(err, "Unable to decode test file")
}

executeLifecycle(kubeTest.Spec.Lifecycle.PostStart, client)

results := runTests(client, kubeTest)
results.threshold = threshold
results.total = len(kubeTest.Spec.Tests)
results.print()

executeLifecycle(kubeTest.Spec.Lifecycle.PreStop, client)

log.Info("Passed", "true", "Passed Test")
}
Expand Down Expand Up @@ -84,7 +87,7 @@ func runTests(client *kubernetes.Clientset, kubeTest *kubeTest) *testResult {
}

func runKubeTester(kubetester kubeTester, i test, res *testResult) {
if result, err := kubetester.test(i.ObjectRef); err != nil {
if result, err := kubetester.test(i.Resource); err != nil {
res.invalid++
} else if result == false {
res.failed++
Expand Down
13 changes: 12 additions & 1 deletion pkg/kubetest/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ func getPod(client *kubernetes.Clientset, name, namespace string) ([]v1.Pod, err
}

func listPods(client *kubernetes.Clientset, namespace string, listOptions *metav1.ListOptions) ([]v1.Pod, error) {
log.InfoWithFields(map[string]interface{}{
"kind": "Pod",
"Namespace": namespace,
"labelkey": listOptions.LabelSelector,
}, "Retriving object")

pods, err := client.CoreV1().Pods(namespace).List(*listOptions)
return pods.Items, err
if err != nil {
log.Error(err, "Unable to retrieve object")
return nil, err
}

return pods.Items, nil
}
Loading

0 comments on commit 3da02ef

Please sign in to comment.