Skip to content
This repository has been archived by the owner on Oct 3, 2019. It is now read-only.

Commit

Permalink
[WIP] Replace oc commands in OperatorSource automated test with clien…
Browse files Browse the repository at this point in the history
…t-go

Signed-off-by: Pratik Jagrut <[email protected]>
  • Loading branch information
Pratik Jagrut committed May 18, 2019
1 parent fdeb4b9 commit 497604f
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 97 deletions.
141 changes: 44 additions & 97 deletions test/operatorsource/basic_test.go
Original file line number Diff line number Diff line change
@@ -1,146 +1,93 @@
package operatorsource

import (
"bytes"
"fmt"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
"os"
"os/exec"
"strings"
"testing"

"github.com/stretchr/testify/require"
)

const ShellToUse = "bash"

func Shellout(command string) (string, string, error) {
var stdout bytes.Buffer
var stderr bytes.Buffer
cmd := exec.Command(ShellToUse, "-c", command)
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
return stdout.String(), stderr.String(), err
}
var (
Client = NewTestClient()
namespace = "openshift-operators"
subName = "devconsole"
subscription, suberr = Client.GetSubscription(subName, namespace)
)

func Test_OperatorSource_oc_commands(t *testing.T) {
func Test_OperatorSource(t *testing.T) {

defer CleanUp(t)

t.Run("login", func(t *testing.T) { Login(t) })
t.Run("subscription", func(t *testing.T) { Subscription(t) })
t.Run("install plan", func(t *testing.T) { InstallPlan(t) })
t.Run("operator pod", func(t *testing.T) { OperatorPod(t) })
}

func Login(t *testing.T) {
// Start - Login to oc
out, _, err := Shellout("oc login -u " + os.Getenv("OC_LOGIN_USERNAME") + " -p " + os.Getenv("OC_LOGIN_PASSWORD"))
if err != nil {
t.Fatalf("error: %v\n", err)
} else {
require.True(t, strings.Contains(out, "Login successful."), "Expecting successful login")
}
}

func Subscription(t *testing.T) {
// 1) Verify that the subscription was created
out, errout, err := Shellout("oc get sub devconsole -n openshift-operators")
if err != nil {
t.Logf("stdout: %s\n", out)
t.Logf("stderr: %s\n", errout)
t.Fatalf("error: %v\n", err)
} else {
require.True(t, strings.Contains(out, "devconsole"), "Expecting the subscription name to be found")
require.True(t, strings.Contains(out, "installed-custom-openshift-operators"), "Expecting the subscription namespace to be found")
if suberr != nil {
t.Fatal(suberr)
}
fmt.Printf("Subscription Name: %s\nCatalog Source: %s\n", subscription.Name, subscription.Spec.CatalogSource)
require.Equal(t, subName, subscription.Name)
require.Equal(t, "installed-custom-openshift-operators", subscription.Spec.CatalogSource)
}

func InstallPlan(t *testing.T) {
// 2) Find the name of the install plan
out, errout, err := Shellout("oc get sub devconsole -n openshift-operators -o jsonpath='{.status.installplan.name}'")
var installPlan string
installPlanName := subscription.Status.Install.Name
fmt.Printf("Install Plan Name: %s\n", installPlanName)
installPlan, err := Client.GetInstallPlan(installPlanName, namespace)
if err != nil {
t.Logf("stdout: %s\n", out)
t.Logf("stderr: %s\n", errout)
t.Fatalf("error: %v\n", err)
} else {
installPlan = out
t.Fatal(err)
}

// 3) Verify the install plan
out, errout, err = Shellout(fmt.Sprintf("oc get installplan %s -n openshift-operators", installPlan))
if err != nil {
t.Logf("stdout: %s\n", out)
t.Logf("stderr: %s\n", errout)
t.Fatalf("error: %v\n", err)
} else {
require.True(t, strings.Contains(out, installPlan), "Expecting the Install Plan name to be found")
require.True(t, strings.Contains(out, "devconsole-operator.v0.1.0"), "Expecting the Operator release to be found")
require.True(t, strings.Contains(out, "Automatic"), "Expecting the approval method to be found")
require.True(t, strings.Contains(out, "true"), "Expecting the approved state to be found")
fmt.Printf("CSV: %v\n", installPlan.Spec.ClusterServiceVersionNames[0])
fmt.Printf("Install Plan Approval: %v\n", installPlan.Spec.Approval)
fmt.Printf("Install Plan Approved: %v\n", installPlan.Spec.Approved)

require.Equal(t, "devconsole-operator.v0.1.0", installPlan.Spec.ClusterServiceVersionNames[0])
require.Equal(t, "Automatic", string(installPlan.Spec.Approval))
if !installPlan.Spec.Approved {
require.FailNow(t, "Install plan approved is false")
}
}

func OperatorPod(t *testing.T) {
// Verify that the operator's pod is running
out, errout, err := Shellout("oc get pods -l name=devconsole-operator -n openshift-operators -o jsonpath='{.items[*].status.phase}'")
// 3) Check operator pod status, fail status != Running
label := "name=devconsole-operator"
pod, err := Client.GetPodByLabel(label, namespace)
if err != nil {
t.Logf("stdout: %s\n", out)
t.Logf("stderr: %s\n", errout)
t.Fatalf("error: %v\n", err)
} else {
require.True(t, strings.Contains(out, "Running"), "Expecting the state of the Operator pod to be running")
t.Fatal(err)
}
if pod == nil {
t.Fatal("pod returned empty")
}
fmt.Printf("Pod Name: %v\nPod status: %v\n", pod.Name, pod.Status.Phase)
require.Equal(t, pod.Status.Phase, corev1.PodRunning)
}

func CleanUp(t *testing.T) {
// Clean up resources
operatorSourceName := os.Getenv("OPSRC_NAME")
operatorVersion := os.Getenv("DEVCONSOLE_OPERATOR_VERSION")

out, errout, err := Shellout(fmt.Sprintf("oc delete opsrc %s -n openshift-marketplace", operatorSourceName))
if err != nil {
t.Logf("stdout: %s\n", out)
t.Logf("stderr: %s\n", errout)
t.Logf("error: %v\n", err)
} else {
t.Logf(out)
}

out, errout, err = Shellout("oc delete sub devconsole -n openshift-operators")
err := Client.Delete("installplan", subscription.Status.Install.Name, namespace)
if err != nil {
t.Logf("stdout: %s\n", out)
t.Logf("stderr: %s\n", errout)
t.Logf("error: %v\n", err)
} else {
t.Logf(out)
t.Logf("Error: %v\n", err)
}

out, errout, err = Shellout("oc delete catsrc installed-custom-openshift-operators -n openshift-operators")
err = Client.Delete("catsrc", subscription.Spec.CatalogSource, namespace)
if err != nil {
t.Logf("stdout: %s\n", out)
t.Logf("stderr: %s\n", errout)
t.Logf("error: %v\n", err)
} else {
t.Logf(out)
t.Logf("Error: %v\n", err)
}

out, errout, err = Shellout("oc delete csc installed-custom-openshift-operators -n openshift-marketplace")
err = Client.Delete("sub", subName, namespace)
if err != nil {
t.Logf("stdout: %s\n", out)
t.Logf("stderr: %s\n", errout)
t.Logf("error: %v\n", err)
} else {
t.Logf(out)
t.Logf("Error: %v\n", err)
}

out, errout, err = Shellout(fmt.Sprintf("oc delete csv devconsole-operator.v%s -n openshift-operators", operatorVersion))
csv := fmt.Sprintf("devconsole-operator.v%s", operatorVersion)
err = Client.Delete("csv", csv, namespace)
if err != nil {
t.Logf("stdout: %s\n", out)
t.Logf("stderr: %s\n", errout)
t.Logf("error: %v\n", err)
} else {
t.Logf(out)
t.Logf("Error: %v\n", err)
}
}
120 changes: 120 additions & 0 deletions test/operatorsource/opsrc_helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package operatorsource

import (
"errors"
"fmt"
apis_v1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
client "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client"
v1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned/typed/operators/v1alpha1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"log"
"os"
)

//ClientSetK8sCoreAPI returns new Clientset for the given config, use to interact with K8s resources like pods
func ClientSetK8sCoreAPI(kubeconfig string) *kubernetes.Clientset {
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
log.Fatal(err)
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
log.Fatal(err)
}
return clientset
}

//ClientSet Creates clientset for given config, use to interact with custom resources
func ClientSet(kubeconfig string) v1alpha1.OperatorsV1alpha1Interface {
client, err := client.NewClient(kubeconfig)
if err != nil {
log.Fatal(err)
}
return client.OperatorsV1alpha1()
}

// TestClient wraps all the clientsets required while testing
type TestClient struct {
K8sClient *kubernetes.Clientset
OperatorClient v1alpha1.OperatorsV1alpha1Interface
}

//NewTestClient initialises the TestClient
func NewTestClient() *TestClient {
kubeconfig := os.Getenv("KUBECONFIG")

return &TestClient{
K8sClient: ClientSetK8sCoreAPI(kubeconfig),
OperatorClient: ClientSet(kubeconfig),
}
}

// GetPodByLabel is a function that takes label and namespace and returns the pod and error
func (tc *TestClient) GetPodByLabel(label string, namespace string) (*corev1.Pod, error) {

pods, err := tc.K8sClient.CoreV1().Pods(namespace).List(metav1.ListOptions{LabelSelector: label})
if err != nil {
return nil, err
}
if len(pods.Items) == 0 {
return nil, nil
}
return &pods.Items[0], nil
}

//GetSubscription returns subscription struct
func (tc *TestClient) GetSubscription(subName, namespace string) (*apis_v1alpha1.Subscription, error) {
subscription, err := tc.OperatorClient.Subscriptions(namespace).Get(subName, metav1.GetOptions{})
if err != nil {
return nil, err
}

return subscription, nil
}

//GetInstallPlan returns install plan struct
func (tc *TestClient) GetInstallPlan(installPlanName, namespace string) (*apis_v1alpha1.InstallPlan, error) {

installPlan, err := tc.OperatorClient.InstallPlans(namespace).Get(installPlanName, metav1.GetOptions{})
if err != nil {
return nil, err
}
return installPlan, nil
}

//Delete takes kind, name and namespace of the resource and deletes it. Returns an error if one occurs.
func (tc *TestClient) Delete(resource, name, namespace string) error {
switch resource {
case "subscription", "sub":
err := tc.OperatorClient.Subscriptions(namespace).Delete(name, &metav1.DeleteOptions{})
if err != nil {
return err
}
return nil
case "installplan":
err := tc.OperatorClient.InstallPlans(namespace).Delete(name, &metav1.DeleteOptions{})
if err != nil {
return err
}
return nil
case "catalogsource", "catsrc":
err := tc.OperatorClient.CatalogSources(namespace).Delete(name, &metav1.DeleteOptions{})
if err != nil {
return err
}
return nil
case "clusterserviceversion", "csv":
err := tc.OperatorClient.ClusterServiceVersions(namespace).Delete(name, &metav1.DeleteOptions{})
if err != nil {
return err
}
return nil
default:
option := fmt.Sprintf("Invalid resource: %s", resource)
return errors.New(option)

}
}

0 comments on commit 497604f

Please sign in to comment.