Skip to content

Commit

Permalink
add e2e for genectl
Browse files Browse the repository at this point in the history
  • Loading branch information
wackxu committed Nov 15, 2018
1 parent 78933ef commit 220b66c
Show file tree
Hide file tree
Showing 9 changed files with 273 additions and 16 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ test:
go test `go list ./... | grep -v -e 'vendor' -e 'test'` $(TESTARGS)
go vet `go list ./... | grep -v vendor`

e2e: KUBECONFIG?=$(HOME)/.kube/config
e2e: KUBECONFIG?=$(HOME)/.kube/config

e2e:
./hack/e2e.sh $(IMAGE_NAME):$(TAG) $(KUBECONFIG)
./hack/e2e.sh $(IMAGE_NAME):$(TAG) $(KUBECONFIG) ./bin/genectl
25 changes: 17 additions & 8 deletions cmd/genectl/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,17 +253,26 @@ func TransWorkflow2Execution(workflow *Workflow) (*execv1alpha1.Execution, error
// we have alreay merge workflows command and commandIter.
task.CommandSet = jobInfo.Commands

// parse Res
cpuNum := strings.TrimRight(jobInfo.Resources.Cpu, "cC")
cpuQuantity, err := resource.ParseQuantity(cpuNum)
if err != nil {
return nil, fmt.Errorf("parse Res quantity error: %v", err)
var cpuQuantity resource.Quantity
var memoryQuantity resource.Quantity
var err error

// parse cpu
if len(jobInfo.Resources.Cpu) > 0 {
cpuNum := strings.TrimRight(jobInfo.Resources.Cpu, "cC")
cpuQuantity, err = resource.ParseQuantity(cpuNum)
if err != nil {
return nil, fmt.Errorf("parse cpu quantity error: %v", err)
}
}
// parse memory
memoryQuantity, err := resource.ParseQuantity(jobInfo.Resources.Memory)
if err != nil {
return nil, fmt.Errorf("parse mem quantity error: %v", err)
if len(jobInfo.Resources.Memory) > 0 {
memoryQuantity, err = resource.ParseQuantity(jobInfo.Resources.Memory)
if err != nil {
return nil, fmt.Errorf("parse mem quantity error: %v", err)
}
}

task.Resources = execv1alpha1.ResourceRequirements{
Cpu: cpuQuantity,
Memory: memoryQuantity,
Expand Down
2 changes: 1 addition & 1 deletion hack/e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ cp gene2e ./hack/
unset http_proxy
unset https_proxy

./gene2e --image=$1 --kubeconfig=$2
./gene2e --image=$1 --kubeconfig=$2 --genectl=$3

rm gene2e

Expand Down
122 changes: 122 additions & 0 deletions test/e2e/genectl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
Copyright 2018 The Kubegene 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 e2e

import (
"os"
"os/exec"
"path/filepath"

"github.com/golang/glog"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/client-go/kubernetes"

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

var GOPATH = os.Getenv("GOPATH")

var ToolRepo = filepath.Join(GOPATH, "src/kubegene.io/kubegene/example/tools")

var _ = DescribeGene("genectl", func(gtc *GeneTestContext) {
var ns string
var kubeClient kubernetes.Interface

BeforeEach(func() {
ns = gtc.Config.Namespace
kubeClient = gtc.KubeClient
})

AfterEach(func() {
})

It("sub single job", func() {
By("Make dir for test")
err := execCommand("mkdir", []string{"-p", "/tmp/subjob"})
Expect(err).NotTo(HaveOccurred())

By("Prepare shell script")
err = execCommand("cp", []string{"example/single-job/print.sh", "/tmp/subjob/"})
Expect(err).NotTo(HaveOccurred())

createVolumeAndClaim("example/single-job/subjob-pv.yaml", "example/single-job/subjob-pvc.yaml", ns, kubeClient)

By("Execute sub job command")
cmd := NewGenectlCommand("sub", "job", "/tmp/subjob/print.sh", "--tool=nginx:latest", "--pvc=subjob-pvc", "--tool-repo="+ToolRepo)
output := cmd.ExecOrDie()
glog.Infof("output: %v", output)
})

It("sub group job", func() {
By("Make dir for test")
err := execCommand("mkdir", []string{"-p", "/tmp/subrepjob"})
Expect(err).NotTo(HaveOccurred())

By("Prepare shell script")
err = execCommand("cp", []string{"example/group-job/print-date.sh", "/tmp/subrepjob/"})
Expect(err).NotTo(HaveOccurred())
err = execCommand("cp", []string{"example/group-job/print-number.sh", "/tmp/subrepjob/"})
Expect(err).NotTo(HaveOccurred())
err = execCommand("cp", []string{"example/group-job/repjob.sh", "/tmp/subrepjob/"})
Expect(err).NotTo(HaveOccurred())

createVolumeAndClaim("example/group-job/subrepjob-pv.yaml", "example/group-job/subrepjob-pvc.yaml", ns, kubeClient)

By("Execute sub repjob command")
cmd := NewGenectlCommand("sub", "repjob", "/tmp/subrepjob/repjob.sh", "--tool=nginx:latest", "--pvc=subrepjob-pvc", "--tool-repo="+ToolRepo)
output := cmd.ExecOrDie()
glog.Infof("output: %v", output)
})

It("sub workflow", func() {
createVolumeAndClaim("example/simple-sample/sample-pv.yaml", "example/simple-sample/sample-pvc.yaml", ns, kubeClient)

By("Execute sub workflow command")
cmd := NewGenectlCommand("sub", "workflow", "example/simple-sample/simple-sample.yaml", "--tool-repo="+ToolRepo)
output := cmd.ExecOrDie()
glog.Infof("output: %v", output)
})
})

func createVolumeAndClaim(volumeFile, claimFile, ns string, kubeClient kubernetes.Interface) {
By("Create a volume")
volume, err := volumeFromManifest(volumeFile)
Expect(err).NotTo(HaveOccurred())
_, err = kubeClient.CoreV1().PersistentVolumes().Create(volume)
Expect(err == nil || errors.IsAlreadyExists(err)).To(Equal(true))

By("Create a claim")
claim, err := claimFromManifest(claimFile)
Expect(err).NotTo(HaveOccurred())
claim.Namespace = ns
_, err = kubeClient.CoreV1().PersistentVolumeClaims(ns).Create(claim)
Expect(err == nil || errors.IsAlreadyExists(err)).To(Equal(true))

err = WaitForPersistentVolumeBound(kubeClient, volume.Name)
Expect(err).NotTo(HaveOccurred())

err = WaitForPersistentVolumeClaimBound(kubeClient, ns, claim.Name)
Expect(err).NotTo(HaveOccurred())
}

func execCommand(name string, args []string) error {
cmd := exec.Command(name, args...)
output, err := cmd.CombinedOutput()
glog.Infof("command: %v, output: %v", name, string(output))
return err
}
94 changes: 94 additions & 0 deletions test/e2e/genectlWrapper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
Copyright 2018 The Kubegene 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 e2e

import (
"bytes"
"fmt"
"os/exec"
"strings"
"syscall"
"time"

"github.com/golang/glog"
. "github.com/onsi/gomega"
)

type genectlWrapper struct {
cmd *exec.Cmd
timeout <-chan time.Time
}

func NewGenectlCommand(args ...string) *genectlWrapper {
ctlWrapper := new(genectlWrapper)
ctlWrapper.cmd = GenectlCmd(args...)
return ctlWrapper
}

// GenectlCmd runs the genectl executable through the wrapper script.
func GenectlCmd(args ...string) *exec.Cmd {
defaultArgs := []string{}

if geneTestContext.Config.KubeConfig != "" {
defaultArgs = append(defaultArgs, "--kubeconfig="+geneTestContext.Config.KubeConfig)
}
genectlArgs := append(defaultArgs, args...)

//We allow users to specify path to genectl.
cmd := exec.Command(geneTestContext.Config.GenectlPath, genectlArgs...)

//caller will invoke this and wait on it.
return cmd
}

func (ctlWrapper genectlWrapper) ExecOrDie() string {
str, err := ctlWrapper.Exec()
Expect(err).NotTo(HaveOccurred())
return str
}

func (ctlWrapper genectlWrapper) Exec() (string, error) {
var stdout, stderr bytes.Buffer
cmd := ctlWrapper.cmd
cmd.Stdout, cmd.Stderr = &stdout, &stderr

glog.Infof("Running '%s %s'", cmd.Path, strings.Join(cmd.Args, " "))
if err := cmd.Start(); err != nil {
return "", fmt.Errorf("error starting %v:\nCommand stdout:\n%v\nstderr:\n%v\nerror:\n%v\n", cmd, cmd.Stdout, cmd.Stderr, err)
}
errCh := make(chan error, 1)
go func() {
errCh <- cmd.Wait()
}()
select {
case err := <-errCh:
if err != nil {
var rc int = 127
if ee, ok := err.(*exec.ExitError); ok {
rc = int(ee.Sys().(syscall.WaitStatus).ExitStatus())
glog.Infof("rc: %d", rc)
}
return "", fmt.Errorf("error running %v:\nCommand stdout:\n%v\nstderr:\n%v\nerror:\n%v\n", cmd, cmd.Stdout, cmd.Stderr, err)
}
case <-ctlWrapper.timeout:
ctlWrapper.cmd.Process.Kill()
return "", fmt.Errorf("timed out waiting for command %v:\nCommand stdout:\n%v\nstderr:\n%v\n", cmd, cmd.Stdout, cmd.Stderr)
}
glog.Infof("stderr: %q", stderr.String())
glog.Infof("stdout: %q", stdout.String())
return stdout.String(), nil
}
30 changes: 30 additions & 0 deletions test/e2e/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,3 +269,33 @@ func readFile(path string) ([]byte, error) {
data, err := ioutil.ReadFile(absPath)
return data, err
}

func volumeFromManifest(fileName string) (*v1.PersistentVolume, error) {
data, err := readFile(fileName)
if err != nil {
return nil, err
}

var persistentVolume v1.PersistentVolume
err = yaml.Unmarshal(data, &persistentVolume)
if err != nil {
return nil, err
}

return &persistentVolume, nil
}

func claimFromManifest(fileName string) (*v1.PersistentVolumeClaim, error) {
data, err := readFile(fileName)
if err != nil {
return nil, err
}

var claim v1.PersistentVolumeClaim
err = yaml.Unmarshal(data, &claim)
if err != nil {
return nil, err
}

return &claim, nil
}
File renamed without changes.
11 changes: 6 additions & 5 deletions test/e2e/test_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@ import (
. "github.com/onsi/gomega"
)

var gtc *GeneTestContext
var geneTestContext *GeneTestContext

// Config provides the configuration for the e2e tests.
type Config struct {
KubeConfig string
KubeDagImage string
Namespace string
GenectlPath string
}

// GeneTestContext holds the variables that each test can depend on. It
Expand All @@ -47,21 +48,21 @@ type GeneTestContext struct {
}

func Test(t *testing.T, config *Config) {
gtc = &GeneTestContext{
geneTestContext = &GeneTestContext{
Config: config,
}

registerTestsInGinkgo(gtc)
registerTestsInGinkgo(geneTestContext)
RegisterFailHandler(Fail)
RunSpecs(t, "Kubegene Test Suite")
}

var _ = BeforeSuite(func() {
gtc.setup()
geneTestContext.setup()
})

var _ = AfterSuite(func() {
gtc.teardown()
geneTestContext.teardown()
})

func (gtc *GeneTestContext) setup() {
Expand Down
1 change: 1 addition & 0 deletions test/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const Kubegene = "kubegene"

func init() {
flag.StringVar(&config.KubeConfig, "kubeconfig", "", "The kube config path")
flag.StringVar(&config.GenectlPath, "genectl", "", "The path of genectl binary")
flag.StringVar(&config.KubeDagImage, "image", "", "The kubedag image")
flag.StringVar(&config.Namespace, "namespace", "", "Namespace to run the test")
flag.Set("logtostderr", "true")
Expand Down

0 comments on commit 220b66c

Please sign in to comment.