Skip to content

Commit

Permalink
Merge pull request #181 from Liujingfang1/memcached
Browse files Browse the repository at this point in the history
Add test for memcached-api-server project
  • Loading branch information
droot committed May 22, 2018
2 parents 4507935 + ac46db0 commit f1bc52d
Show file tree
Hide file tree
Showing 20 changed files with 625 additions and 3 deletions.
145 changes: 145 additions & 0 deletions samples/internal/test/e2e/kubebuildertest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package e2e

import (
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
)

type KubebuilderTest struct {
Dir string
}

func NewKubebuilderTest(dir, binDir string) *KubebuilderTest {
kt := KubebuilderTest{Dir: dir}
os.Setenv("TEST_ASSET_KUBECTL", strings.Join([]string{binDir, "kubectl"}, "/"))
os.Setenv("TEST_ASSET_KUBE_APISERVER", strings.Join([]string{binDir, "kube-apiserver"}, "/"))
os.Setenv("TEST_ASSET_ETCD", strings.Join([]string{binDir, "etcd"}, "/"))
return &kt
}

func (kt *KubebuilderTest) Generate(generateOptions []string) error {
generateOptions = append([]string{"generate"}, generateOptions...)
cmd := exec.Command("kubebuilder", generateOptions...)
return kt.runCommand(cmd)
}

func (kt *KubebuilderTest) Docs(docsOptions []string) error {
docsOptions = append([]string{"docs"}, docsOptions...)
cmd := exec.Command("kubebuilder", docsOptions...)
return kt.runCommand(cmd)
}

func (kt *KubebuilderTest) Build() error {
var errs []string
cmd := exec.Command("go", "build", "./pkg/...")
err := kt.runCommand(cmd)
if err != nil {
errs = append(errs, err.Error())
}
cmd = exec.Command("go", "build", "./cmd/...")
err = kt.runCommand(cmd)
if err != nil {
errs = append(errs, err.Error())
}
if len(errs) > 0 {
return fmt.Errorf(strings.Join(errs, "\n"))
}
return nil
}

func (kt *KubebuilderTest) Test() error {
var errs []string
cmd := exec.Command("go", "test", "./pkg/...")
err := kt.runCommand(cmd)
if err != nil {
errs = append(errs, err.Error())
}
cmd = exec.Command("go", "test", "./cmd/...")
err = kt.runCommand(cmd)
if err != nil {
errs = append(errs, err.Error())
}
if len(errs) > 0 {
return fmt.Errorf(strings.Join(errs, "\n"))
}
return nil
}

func (kt *KubebuilderTest) CreateConfig(configOptions []string) error {
configOptions = append([]string{"create", "config"}, configOptions...)
cmd := exec.Command("kubebuilder", configOptions...)
return kt.runCommand(cmd)
}

func (kt *KubebuilderTest) Diff(pathA, pathB string) error {
cmd := exec.Command("diff", pathA, pathB)
return kt.runCommand(cmd)
}

func (kt *KubebuilderTest) DiffAll(generatedDir, expectedDir string) error {
files, err := ioutil.ReadDir(expectedDir)
if err != nil {
return err
}
var errs []string
for _, f := range files {
generatedFile := filepath.Join(generatedDir, f.Name())
if _, err := os.Stat(generatedFile); err != nil {
errs = append(errs, err.Error())
} else {
err = kt.Diff(generatedFile, filepath.Join(expectedDir, f.Name()))
if err != nil {
errs = append(errs, err.Error())
}
}
}
if len(errs) > 0 {
return fmt.Errorf(strings.Join(errs, "\n"))
}
return nil
}

func (kt *KubebuilderTest) DepEnsure() error {
cmd := exec.Command("dep", "ensure")
return kt.runCommand(cmd)
}

func (kt *KubebuilderTest) VendorUpdate() error {
cmd := exec.Command("kubebuilder", "vendor", "update")
return kt.runCommand(cmd)
}

func (kt *KubebuilderTest) CleanUp() error {
var errs []string
cmd := exec.Command("kubebuilder", "generate", "clean")
err := kt.runCommand(cmd)
if err != nil {
errs = append(errs, err.Error())
}
cmd = exec.Command("rm", "-r", "docs")
err = kt.runCommand(cmd)
if err != nil {
errs = append(errs, err.Error())
}
if len(errs) > 0 {
return fmt.Errorf(strings.Join(errs, "\n"))
}
return nil
}

func (kt *KubebuilderTest) runCommand(cmd *exec.Cmd) error {
cmd.Dir = kt.Dir
cmd.Env = os.Environ()
command := strings.Join(cmd.Args, " ")
output, err := cmd.Output()
if err != nil {
return fmt.Errorf("%s failed with error: %s", command, string(output))
}
log.Printf("%s finished successfully", command)
return nil
}
72 changes: 72 additions & 0 deletions samples/memcached-api-server/memcached_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package memcached_test

import (
"os"
"path/filepath"
"runtime"
"testing"
"github.com/kubernetes-sigs/kubebuilder/samples/internal/test/e2e"
)

var kubebuilderTest *e2e.KubebuilderTest

func setup() {
_, filename, _, _ := runtime.Caller(0)
projectDir := filepath.Dir(filename)
kubebuilderBin := "/tmp/kubebuilder/bin"
kubebuilderTest = e2e.NewKubebuilderTest(projectDir, kubebuilderBin)
}

func teardown() {
kubebuilderTest.CleanUp()
}

func TestMain(m *testing.M) {
setup()
code := m.Run()
teardown()
os.Exit(code)
}

func TestGenerateBuildTest(t *testing.T) {
err := kubebuilderTest.Generate([]string{"--skip-rbac-validation"})
if err != nil {
t.Errorf(err.Error())
}
err = kubebuilderTest.Build()
if err != nil {
t.Errorf(err.Error())
}
err = kubebuilderTest.Test()
if err != nil {
t.Errorf(err.Error())
}
}

func TestDocs(t *testing.T) {
docsOptions := []string{"--docs-copyright", "Hello", "--title", "World", "--cleanup=false", "--brodocs=false"}
err := kubebuilderTest.Docs(docsOptions)
if err != nil {
t.Errorf(err.Error())
}
docsDir := filepath.Join(kubebuilderTest.Dir, "docs", "reference")
expectedDocsDir := filepath.Join(kubebuilderTest.Dir, "test", "docs", "reference")
err = kubebuilderTest.DiffAll(docsDir, expectedDocsDir)
if err != nil {
t.Errorf(err.Error())
}
}

func TestCreateConfig(t *testing.T) {
configOptions := []string{"--crds"}
err := kubebuilderTest.CreateConfig(configOptions)
if err != nil {
t.Errorf(err.Error())
}
configFile := filepath.Join(kubebuilderTest.Dir, "hack", "install.yaml")
expectedConfigFile := filepath.Join(kubebuilderTest.Dir, "test", "hack", "install.yaml")
err = kubebuilderTest.Diff(configFile, expectedConfigFile)
if err != nil {
t.Errorf(err.Error())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,11 @@ func (bc *MemcachedController) updateMemcachedStatus(mc *myappsv1alpha1.Memcache

// +controller:group=myapps,version=v1alpha1,kind=Memcached,resource=memcacheds
// +informers:group=apps,version=v1,kind=Deployment
// +rbac:rbac:groups=apps,resources=Deployment,verbs=get;list;watch;create;update;patch;delete
// +rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
// +informers:group=apps,version=v1,kind=ReplicaSet
// +rbac:rbac:groups=apps,resources=ReplicaSet,verbs=get;list;watch
// +rbac:groups=apps,resources=replicasets,verbs=get;list;watch
// +informers:group=core,version=v1,kind=Pod
// +rbac:rbac:groups="",resources=Pod,verbs=get;list;watch
// +rbac:groups=core,resources=pods,verbs=get;list;watch
type MemcachedController struct {
args.InjectArgs

Expand Down
10 changes: 10 additions & 0 deletions samples/memcached-api-server/test/docs/reference/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
example_location: "examples"
api_groups:
- "Myapps"
resource_categories:
- name: "Myapps"
include: "myapps"
resources:
- name: "Memcached"
version: "v1alpha1"
group: "myapps"
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

# <strong>Field Definitions</strong>

------------

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
## Initializer v1

Group | Version | Kind
------------ | ---------- | -----------
`meta` | `v1` | `Initializer`



Initializer is information about an initializer that has not yet completed.

<aside class="notice">
Appears In:

<ul>
<li><a href="#initializers-v1">Initializers v1</a></li>
</ul></aside>

Field | Description
------------ | -----------
`name`<br /> *string* | name of the process that is responsible for initializing this object.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
## Initializers v1

Group | Version | Kind
------------ | ---------- | -----------
`meta` | `v1` | `Initializers`



Initializers tracks the progress of initialization.

<aside class="notice">
Appears In:

<ul>
<li><a href="#objectmeta-v1">ObjectMeta v1</a></li>
</ul></aside>

Field | Description
------------ | -----------
`pending`<br /> *[Initializer](#initializer-v1) array* <br /> **patch type**: *merge* <br /> **patch merge key**: *name* | Pending is a list of initializers that must execute in order before this object is visible. When the last pending initializer is removed, and no failing result is set, the initializers struct will be set to nil and the object is considered as initialized and visible to all clients.
`result`<br /> *[Status](#status-v1)* | If result is set with the Failure field, the object will be persisted to storage and then deleted, ensuring that other clients can observe the deletion.

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
## ListMeta v1

Group | Version | Kind
------------ | ---------- | -----------
`meta` | `v1` | `ListMeta`



ListMeta describes metadata that synthetic resources must have, including lists and various status objects. A resource may have only one of {ObjectMeta, ListMeta}.

<aside class="notice">
Appears In:

<ul>
<li><a href="#status-v1">Status v1</a></li>
</ul></aside>

Field | Description
------------ | -----------
`continue`<br /> *string* | continue may be set if the user set a limit on the number of items returned, and indicates that the server has more data available. The value is opaque and may be used to issue another request to the endpoint that served this list to retrieve the next set of available objects. Continuing a list may not be possible if the server configuration has changed or more than a few minutes have passed. The resourceVersion field returned when using this continue value will be identical to the value in the first response.
`resourceVersion`<br /> *string* | String that identifies the server&#39;s internal version of this object that can be used by clients to determine when objects have changed. Value must be treated as opaque by clients and passed unmodified back to the server. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency
`selfLink`<br /> *string* | selfLink is a URL representing this object. Populated by the system. Read-only.

Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@


-----------
# Memcached v1alpha1



Group | Version | Kind
------------ | ---------- | -----------
`myapps` | `v1alpha1` | `Memcached`







Memcached



Field | Description
------------ | -----------
`apiVersion`<br /> *string* | APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources
`kind`<br /> *string* | Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds
`metadata`<br /> *[ObjectMeta](#objectmeta-v1)* |
`spec`<br /> *[MemcachedSpec](#memcachedspec-v1alpha1)* |
`status`<br /> *[MemcachedStatus](#memcachedstatus-v1alpha1)* |


### MemcachedSpec v1alpha1

<aside class="notice">
Appears In:

<ul>
<li><a href="#memcached-v1alpha1">Memcached v1alpha1</a></li>
</ul></aside>

Field | Description
------------ | -----------
`size`<br /> *integer* | INSERT ADDITIONAL SPEC FIELDS - desired state of cluster

### MemcachedStatus v1alpha1

<aside class="notice">
Appears In:

<ul>
<li><a href="#memcached-v1alpha1">Memcached v1alpha1</a></li>
</ul></aside>

Field | Description
------------ | -----------
`nodes`<br /> *string array* | INSERT ADDITIONAL STATUS FIELD - define observed state of cluster





Loading

0 comments on commit f1bc52d

Please sign in to comment.