Skip to content

Commit

Permalink
Merge pull request bitnami-labs#76 from anguslees/integrationtest
Browse files Browse the repository at this point in the history
Add integration framework and tests
  • Loading branch information
anguslees authored Feb 9, 2018
2 parents 9732bc3 + 2400845 commit c8ea403
Show file tree
Hide file tree
Showing 382 changed files with 205,768 additions and 9,627 deletions.
48 changes: 48 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,50 @@ env:
global:
- CONTROLLER_IMAGE_NAME=quay.io/bitnami/sealed-secrets-controller
- CONTROLLER_IMAGE=${CONTROLLER_IMAGE_NAME}:${TRAVIS_TAG:-build-$TRAVIS_BUILD_ID}
- MINIKUBE_WANTUPDATENOTIFICATION=false
- MINIKUBE_WANTREPORTERRORPROMPT=false
- MINIKUBE_HOME=${HOME}
- CHANGE_MINIKUBE_NONE_USER=true
- KUBECONFIG=${HOME}/.kube/config

matrix:
include:
- env: INT_KVERS=v1.9.0 INT_SSC_CONF=sealedsecret-crd.yaml,controller.yaml
- env: INT_KVERS=v1.8.0 INT_SSC_CONF=sealedsecret-crd.yaml,controller.yaml
- env: INT_KVERS=v1.7.0 INT_SSC_CONF=sealedsecret-crd.yaml,controller.yaml
- env: INT_KVERS=v1.7.0 INT_SSC_CONF=sealedsecret-tpr.yaml,controller.yaml
- env: INT_KVERS=v1.6.0 INT_SSC_CONF=sealedsecret-tpr.yaml,controller.yaml

addons:
apt:
packages:
- wget
- ca-certificates

before_install:
- set -e

install:
- go build -i ./...
- |
if [ "$INT_KVERS" != "" ]; then
if ! which minikube; then
wget -O minikube \
https://storage.googleapis.com/minikube/releases/v0.25.0/minikube-$(go env GOOS)-$(go env GOARCH)
install -m 755 minikube $GOPATH/bin/minikube
fi
if ! which kubectl; then
wget https://storage.googleapis.com/kubernetes-release/release/$INT_KVERS/bin/$(go env GOOS)/$(go env GOARCH)/kubectl
install -m 755 kubectl $GOPATH/bin/kubectl
fi
mkdir -p $(dirname $KUBECONFIG)
touch $KUBECONFIG
sudo -E $GOPATH/bin/minikube start --vm-driver=none \
--extra-config apiserver.Authorization.Mode=RBAC \
--kubernetes-version $INT_KVERS
go get github.com/onsi/ginkgo/ginkgo
fi
- >-
wget -O $GOPATH/bin/kubecfg
https://github.com/ksonnet/kubecfg/releases/download/v0.4.0/kubecfg-$(go env GOOS)-$(go env GOARCH)
Expand All @@ -40,6 +78,15 @@ script:
if [ "$TRAVIS_OS_NAME" = linux ]; then
make controller.yaml controller-norbac.yaml sealedsecret-crd.yaml sealedsecret-tpr.yaml CONTROLLER_IMAGE=$CONTROLLER_IMAGE
fi
- |
if [ "$INT_KVERS" != "" ]; then
minikube update-context
minikube status
while ! kubectl cluster-info; do sleep 3; done
kubectl create -f $INT_SSC_CONF
kubectl rollout status deployment/sealed-secrets-controller -n kube-system -w
make integrationtest CONTROLLER_IMAGE=$CONTROLLER_IMAGE
fi
after_script: set +e

Expand Down Expand Up @@ -82,6 +129,7 @@ cache:
directories:
- $GOPATH/pkg
- $GOPATH/bin
- $HOME/.minikube/cache

branches:
only:
Expand Down
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ GOFMT = gofmt

KUBECFG = kubecfg
DOCKER = docker
GINKGO = ginkgo -p

DOCKER_USE_SHA = 0
CONTROLLER_IMAGE = sealed-secrets-controller:latest
KUBECONFIG ?= $(HOME)/.kube/config

# TODO: Simplify this once ./... ignores ./vendor
GO_PACKAGES = ./cmd/... ./pkg/...
Expand Down Expand Up @@ -49,6 +51,10 @@ controller-norbac.yaml: controller-norbac.jsonnet controller.image
test:
$(GO) test $(GO_FLAGS) $(GO_PACKAGES)

integrationtest: kubeseal
# Assumes a k8s cluster exists, with controller already installed
$(GINKGO) -tags 'integration' integration -- -kubeconfig $(KUBECONFIG) -kubeseal-bin $(abspath $<)

vet:
# known issue:
# pkg/client/clientset/versioned/fake/clientset_generated.go:46: literal copies lock value from fakePtr
Expand Down
99 changes: 99 additions & 0 deletions integration/controller_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// +build integration

package integration

import (
"crypto/rsa"
"crypto/x509"
"fmt"

"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/scheme"
corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
certUtil "k8s.io/client-go/util/cert"

ssv1alpha1 "github.com/bitnami-labs/sealed-secrets/pkg/apis/sealed-secrets/v1alpha1"
ssclient "github.com/bitnami-labs/sealed-secrets/pkg/client/clientset/versioned"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

func getData(s *v1.Secret) map[string][]byte {
return s.Data
}

func fetchKeys(c corev1.SecretsGetter) (*rsa.PrivateKey, []*x509.Certificate, error) {
s, err := c.Secrets("kube-system").Get("sealed-secrets-key", metav1.GetOptions{})
if err != nil {
return nil, nil, err
}

privKey, err := certUtil.ParsePrivateKeyPEM(s.Data[v1.TLSPrivateKeyKey])
if err != nil {
return nil, nil, err
}

certs, err := certUtil.ParseCertsPEM(s.Data[v1.TLSCertKey])
if err != nil {
return nil, nil, err
}

if len(certs) == 0 {
return nil, nil, fmt.Errorf("Failed to read any certificates")
}

return privKey.(*rsa.PrivateKey), certs, nil
}

var _ = Describe("create", func() {
var c corev1.CoreV1Interface
var ssc ssclient.Interface
var ns string
const secretName = "testsecret"
var ss *ssv1alpha1.SealedSecret
var s *v1.Secret

BeforeEach(func() {
conf := clusterConfigOrDie()
c = corev1.NewForConfigOrDie(conf)
ssc = ssclient.NewForConfigOrDie(conf)
ns = createNsOrDie(c, "create")
s = &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: ns,
Name: secretName,
},
Data: map[string][]byte{
"foo": []byte("bar"),
},
}
})
AfterEach(func() {
deleteNsOrDie(c, ns)
})

Describe("Simple change", func() {
BeforeEach(func() {
_, certs, err := fetchKeys(c)
Expect(err).NotTo(HaveOccurred())

ss, err = ssv1alpha1.NewSealedSecret(scheme.Codecs, certs[0].PublicKey.(*rsa.PublicKey), s)
Expect(err).NotTo(HaveOccurred())
})
JustBeforeEach(func() {
var err error
ss, err = ssc.BitnamiV1alpha1().SealedSecrets(ns).Create(ss)
Expect(err).NotTo(HaveOccurred())
})

Context("With no existing object (create)", func() {
It("should produce expected Secret", func() {
Eventually(func() (*v1.Secret, error) {
return c.Secrets(ns).Get(secretName, metav1.GetOptions{})
}).Should(WithTransform(getData, Equal(s.Data)))
})
})
})
})
124 changes: 124 additions & 0 deletions integration/integration_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// +build integration

package integration

import (
"bytes"
"flag"
"fmt"
"io"
"os/exec"
"testing"

"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes/scheme"
corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"

ssv1alpha1 "github.com/bitnami-labs/sealed-secrets/pkg/apis/sealed-secrets/v1alpha1"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"

// For client auth plugins
_ "k8s.io/client-go/plugin/pkg/client/auth"
)

var kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
var kubesealBin = flag.String("kubeseal-bin", "kubeseal", "path to kubeseal executable under test")

func clusterConfigOrDie() *rest.Config {
var config *rest.Config
var err error

if *kubeconfig != "" {
config, err = clientcmd.BuildConfigFromFlags("", *kubeconfig)
} else {
config, err = rest.InClusterConfig()
}
if err != nil {
panic(err.Error())
}

return config
}

func createNsOrDie(c corev1.NamespacesGetter, ns string) string {
result, err := c.Namespaces().Create(
&v1.Namespace{
ObjectMeta: metav1.ObjectMeta{
GenerateName: ns,
},
})
if err != nil {
panic(err.Error())
}
name := result.GetName()
fmt.Fprintf(GinkgoWriter, "Created namespace %s\n", name)
return name
}

func deleteNsOrDie(c corev1.NamespacesGetter, ns string) {
err := c.Namespaces().Delete(ns, &metav1.DeleteOptions{})
if err != nil {
panic(err.Error())
}
}

func containsString(haystack []string, needle string) bool {
for _, s := range haystack {
if s == needle {
return true
}
}
return false
}

func runKubeseal(flags []string, input io.Reader, output io.Writer) error {
args := []string{}
if *kubeconfig != "" && !containsString(flags, "--kubeconfig") {
args = append(args, "--kubeconfig", *kubeconfig)
}
args = append(args, flags...)

fmt.Fprintf(GinkgoWriter, "Running %q %q\n", *kubesealBin, args)
cmd := exec.Command(*kubesealBin, args...)
cmd.Stdin = input
cmd.Stdout = output
cmd.Stderr = GinkgoWriter

return cmd.Run()
}

func runKubesealWith(flags []string, input runtime.Object) (runtime.Object, error) {
enc := scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion)
indata, err := runtime.Encode(enc, input)
if err != nil {
return nil, err
}

fmt.Fprintf(GinkgoWriter, "kubeseal input:\n%s", indata)

outbuf := bytes.Buffer{}

if err := runKubeseal(flags, bytes.NewReader(indata), &outbuf); err != nil {
return nil, err
}

fmt.Fprintf(GinkgoWriter, "kubeseal output:\n%s", outbuf.Bytes())

outputObj, err := runtime.Decode(scheme.Codecs.UniversalDecoder(ssv1alpha1.SchemeGroupVersion), outbuf.Bytes())
if err != nil {
return nil, err
}

return outputObj, nil
}

func TestE2e(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "sealed-secrets integration tests")
}
Loading

0 comments on commit c8ea403

Please sign in to comment.