Skip to content

Adds integration tests for ansible operator #582

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 16 additions & 22 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,30 @@ jobs:
env:
- CLUSTER=minikube
- CHANGE_MINIKUBE_NONE_USER=true
script: test/test-go.sh
name: Go on minikube
- before_script: hack/ci/setup-minikube.sh
env:
- CLUSTER=minikube
- CHANGE_MINIKUBE_NONE_USER=true
script: test/test-ansible.sh
name: Ansible on minikube
- before_script: hack/ci/setup-openshift.sh
env: CLUSTER=openshift
script: test/test-go.sh
name: Go on OpenShift
- before_script: hack/ci/setup-openshift.sh
env: CLUSTER=openshift
script: test/test-ansible.sh
name: Ansible on OpenShift

install:
- curl -Lo dep https://github.com/golang/dep/releases/download/v0.5.0/dep-linux-amd64 && chmod +x dep && sudo mv dep /usr/local/bin/
- dep ensure
- make install
# Create example operator directory
- mkdir -p $GOPATH/src/github.com/example-inc

script:
- make install
- go test ./commands/...
- go test ./pkg/...
- go test ./test/e2e/...
- cd test/test-framework
# test framework with defaults
- operator-sdk test local .
# test operator-sdk test flags
- operator-sdk test local . --global-manifest deploy/crd.yaml --namespaced-manifest deploy/namespace-init.yaml --go-test-flags "-parallel 1" --kubeconfig $HOME/.kube/config
# test operator-sdk test local single namespace mode
- kubectl create namespace test-memcached
- operator-sdk test local . --namespace=test-memcached
- kubectl delete namespace test-memcached
# go back to project root
- cd ../..
- go vet ./...
- ./hack/check_license.sh
- ./hack/check_error_case.sh
# Make sure repo is in clean state
- git diff --exit-code
- sudo pip install ansible

after_success:
- echo 'Build succeeded, operator was generated, memcached operator is running on $CLUSTER, and unit/integration tests pass'
Expand Down
1 change: 1 addition & 0 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion hack/ci/setup-minikube.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Download kubectl, which is a requirement for using minikube.
curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/v1.10.1/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/
curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/v1.11.3/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/
# Download minikube.
# We need to pin to an old version due to minikube requiring systemd starting with v0.26.0 and travis not providing it
# - https://github.com/kubernetes/minikube/issues/2704
Expand Down
4 changes: 2 additions & 2 deletions hack/ci/setup-openshift.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ oc cluster up
# Become cluster admin
oc login -u system:admin

# kubectl is needed for the single namespace local test
curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/v1.10.1/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/
# kubectl is needed for the single namespace local test and the ansible tests
curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/v1.11.3/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/
1 change: 1 addition & 0 deletions test/ansible-memcached/defaults.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
size: 1
2 changes: 2 additions & 0 deletions test/ansible-memcached/memfin/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- debug:
msg: "this is a finalizer"
37 changes: 37 additions & 0 deletions test/ansible-memcached/tasks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
- name: start memcached
k8s:
definition:
kind: Deployment
apiVersion: apps/v1
metadata:
name: '{{ meta.name }}-memcached'
namespace: '{{ meta.namespace }}'
labels:
app: memcached
spec:
replicas: "{{size}}"
selector:
matchLabels:
app: memcached
template:
metadata:
labels:
app: memcached
spec:
containers:
- name: memcached
command:
- memcached
- -m=64
- -o
- modern
- -v
image: "docker.io/memcached:1.4.36-alpine"
ports:
- containerPort: 11211
readinessProbe:
tcpSocket:
port: 11211
initialDelaySeconds: 3
periodSeconds: 3
3 changes: 3 additions & 0 deletions test/ansible-memcached/watches-finalizer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
finalizer:
name: finalizer.ansible.example.com
role: /opt/ansible/roles/memfin
24 changes: 24 additions & 0 deletions test/ansible-operator/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
FROM ansible/ansible-runner

RUN pip install --upgrade setuptools
RUN pip install openshift ansible-runner-http

RUN echo "localhost ansible_connection=local" > /etc/ansible/hosts \
&& echo '[defaults]' > /etc/ansible/ansible.cfg \
&& echo 'roles_path = /opt/ansible/roles' >> /etc/ansible/ansible.cfg \
&& echo 'library = /usr/share/ansible/openshift' >> /etc/ansible/ansible.cfg

ENV OPERATOR=/usr/local/bin/ansible-operator \
USER_UID=1001 \
USER_NAME=ansible-operator\
HOME=/opt/ansible

# install operator binary
ADD ansible-operator ${OPERATOR}

COPY bin /usr/local/bin
RUN /usr/local/bin/user_setup

ENTRYPOINT ["/usr/local/bin/entrypoint"]

USER ${USER_UID}
2 changes: 2 additions & 0 deletions test/ansible-operator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
This directory temporarily holds the artifacts that are required to build the
ansible operator base image, until they find a more permanent home.
12 changes: 12 additions & 0 deletions test/ansible-operator/bin/entrypoint
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash -e

# This is documented here:
# https://docs.openshift.com/container-platform/3.10/creating_images/guidelines.html#openshift-specific-guidelines

if ! whoami &>/dev/null; then
if [ -w /etc/passwd ]; then
echo "${USER_NAME:-runner}:x:$(id -u):$(id -g):${USER_NAME:-runner} user:${HOME}:/sbin/nologin" >> /etc/passwd
fi
fi

exec "${OPERATOR:-/usr/local/bin/ansible-operator}"
13 changes: 13 additions & 0 deletions test/ansible-operator/bin/user_setup
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/sh
set -x

# ensure $HOME exists and is accessible by group 0 (we don't know what the runtime UID will be)
mkdir -p ${HOME}
chown ${USER_UID}:0 ${HOME}
chmod ug+rwx ${HOME}

# runtime user will need to be able to self-insert in /etc/passwd
chmod g+rw /etc/passwd

# no need for this script to remain in the image after running
rm $0
94 changes: 94 additions & 0 deletions test/ansible-operator/cmd/ansible-operator/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Copyright 2018 The Operator-SDK Authors
//
// 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 main

import (
"flag"
"log"
"math/rand"
"runtime"
"time"

"github.com/operator-framework/operator-sdk/pkg/ansible/controller"
proxy "github.com/operator-framework/operator-sdk/pkg/ansible/proxy"
"github.com/operator-framework/operator-sdk/pkg/ansible/runner"
sdkVersion "github.com/operator-framework/operator-sdk/version"
"sigs.k8s.io/controller-runtime/pkg/client/config"
"sigs.k8s.io/controller-runtime/pkg/manager"
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
"sigs.k8s.io/controller-runtime/pkg/runtime/signals"

"github.com/sirupsen/logrus"
)

func printVersion() {
logrus.Infof("Go Version: %s", runtime.Version())
logrus.Infof("Go OS/Arch: %s/%s", runtime.GOOS, runtime.GOARCH)
logrus.Infof("operator-sdk Version: %v", sdkVersion.Version)
}

func main() {
flag.Parse()
logf.SetLogger(logf.ZapLogger(false))

mgr, err := manager.New(config.GetConfigOrDie(), manager.Options{})
if err != nil {
log.Fatal(err)
}

printVersion()
done := make(chan error)

// start the proxy
proxy.RunProxy(done, proxy.Options{
Address: "localhost",
Port: 8888,
KubeConfig: mgr.GetConfig(),
})

// start the operator
go runSDK(done, mgr)

// wait for either to finish
err = <-done
if err == nil {
logrus.Info("Exiting")
} else {
logrus.Fatal(err.Error())
}
}

func runSDK(done chan error, mgr manager.Manager) {
namespace := "default"
watches, err := runner.NewFromWatches("/opt/ansible/watches.yaml")
if err != nil {
logrus.Error("Failed to get watches")
done <- err
return
}
rand.Seed(time.Now().Unix())
c := signals.SetupSignalHandler()

for gvk, runner := range watches {
controller.Add(mgr, controller.Options{
GVK: gvk,
Namespace: namespace,
Runner: runner,
StopChannel: c,
})
}
log.Fatal(mgr.Start(c))
done <- nil
}
48 changes: 48 additions & 0 deletions test/test-ansible.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env bash

set -ev

# switch to the "default" namespace if on openshift, to match the minikube test
if which oc 2>/dev/null; then oc project default; fi

# build operator binary and base image
go build -o test/ansible-operator/ansible-operator test/ansible-operator/cmd/ansible-operator/main.go
pushd test
pushd ansible-operator
docker build -t quay.io/water-hole/ansible-operator .
popd

# create and build the operator
operator-sdk new memcached-operator --api-version=ansible.example.com/v1alpha1 --kind=Memcached --type=ansible
cp ansible-memcached/tasks.yml memcached-operator/roles/Memcached/tasks/main.yml
cp ansible-memcached/defaults.yml memcached-operator/roles/Memcached/defaults/main.yml
cp -a ansible-memcached/memfin memcached-operator/roles/
cat ansible-memcached/watches-finalizer.yaml >> memcached-operator/watches.yaml

pushd memcached-operator
operator-sdk build quay.io/example/memcached-operator:v0.0.2
sed -i 's|REPLACE_IMAGE|quay.io/example/memcached-operator:v0.0.2|g' deploy/operator.yaml
sed -i 's|Always|Never|g' deploy/operator.yaml

# deploy the operator
kubectl create -f deploy/rbac.yaml
kubectl create -f deploy/crd.yaml
kubectl create -f deploy/operator.yaml

# wait for operator pod to run
kubectl rollout status deployment/memcached-operator
kubectl logs deployment/memcached-operator

# create CR
kubectl create -f deploy/cr.yaml
until kubectl get deployment -l app=memcached | grep memcached; do sleep 1; done
memcached_deployment=$(kubectl get deployment -l app=memcached -o jsonpath="{..metadata.name}")
kubectl rollout status deployment/${memcached_deployment}
kubectl logs deployment/${memcached_deployment}

# Test finalizer
kubectl delete -f deploy/cr.yaml --wait=true
kubectl logs deployment/memcached-operator | grep "this is a finalizer"

popd
popd
28 changes: 28 additions & 0 deletions test/test-go.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env bash

set -e

go test ./commands/...
go test ./pkg/...
go test ./test/e2e/...
cd test/test-framework

# test framework with defaults
operator-sdk test local .

# test operator-sdk test flags
operator-sdk test local . --global-manifest deploy/crd.yaml --namespaced-manifest deploy/namespace-init.yaml --go-test-flags "-parallel 1" --kubeconfig $HOME/.kube/config

# test operator-sdk test local single namespace mode
kubectl create namespace test-memcached
operator-sdk test local . --namespace=test-memcached
kubectl delete namespace test-memcached

# go back to project root
cd ../..
go vet ./...
./hack/check_license.sh
./hack/check_error_case.sh

# Make sure repo is in clean state
git diff --exit-code